X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=secnet.git;a=blobdiff_plain;f=netlink.c;h=794bffe7b5c6bf3755e7b9c64817b2816eed8865;hp=5d586d03dbd14e4e6b9ba92a36db1b5c0ecb50b3;hb=34d3bf4cdcb2d2938c3b92573f66815e4d9392ac;hpb=45a1170652384baf744a5e61d576af534c7b8b14 diff --git a/netlink.c b/netlink.c index 5d586d0..794bffe 100644 --- a/netlink.c +++ b/netlink.c @@ -238,7 +238,7 @@ static struct icmphdr *netlink_icmp_tmpl(struct netlink *st, struct icmphdr *h; BUF_ALLOC(&st->icmp,"netlink_icmp_tmpl"); - buffer_init(&st->icmp,st->max_start_pad); + buffer_init(&st->icmp,calculate_max_start_pad()); h=buf_append(&st->icmp,sizeof(*h)); h->iph.version=4; @@ -293,6 +293,7 @@ static bool_t netlink_icmp_may_reply(struct buffer_if *buf) struct icmphdr *icmph; uint32_t source; + if (buf->size < (int)sizeof(struct icmphdr)) return False; iph=(struct iphdr *)buf->start; icmph=(struct icmphdr *)buf->start; if (iph->protocol==1) { @@ -338,6 +339,7 @@ static bool_t netlink_icmp_may_reply(struct buffer_if *buf) */ static uint16_t netlink_icmp_reply_len(struct buffer_if *buf) { + if (buf->size < (int)sizeof(struct iphdr)) return 0; struct iphdr *iph=(struct iphdr *)buf->start; uint16_t hlen,plen; @@ -354,11 +356,11 @@ static void netlink_icmp_simple(struct netlink *st, struct buffer_if *buf, struct netlink_client *client, uint8_t type, uint8_t code) { - struct iphdr *iph=(struct iphdr *)buf->start; struct icmphdr *h; uint16_t len; if (netlink_icmp_may_reply(buf)) { + struct iphdr *iph=(struct iphdr *)buf->start; len=netlink_icmp_reply_len(buf); h=netlink_icmp_tmpl(st,ntohl(iph->saddr),len); h->type=type; h->code=code; @@ -389,6 +391,7 @@ static bool_t netlink_check(struct netlink *st, struct buffer_if *buf, return False; \ }while(0) + if (buf->size < (int)sizeof(struct iphdr)) BAD("len %"PRIu32"",buf->size); struct iphdr *iph=(struct iphdr *)buf->start; int32_t len; @@ -406,6 +409,28 @@ static bool_t netlink_check(struct netlink *st, struct buffer_if *buf, #undef BAD } +/* Deliver a packet _to_ client; used after we have decided + * what to do with it (and just to check that the client has + * actually registered a delivery function with us). */ +static void netlink_client_deliver(struct netlink *st, + struct netlink_client *client, + uint32_t source, uint32_t dest, + struct buffer_if *buf) +{ + if (!client->deliver) { + string_t s,d; + s=ipaddr_to_string(source); + d=ipaddr_to_string(dest); + Message(M_ERR,"%s: dropping %s->%s, client not registered\n", + st->name,s,d); + free(s); free(d); + BUF_FREE(buf); + return; + } + client->deliver(client->dst, buf); + client->outcount++; +} + /* Deliver a packet. "client" is the _origin_ of the packet, not its destination, and is NULL for packets from the host and packets generated internally in secnet. */ @@ -413,6 +438,13 @@ static void netlink_packet_deliver(struct netlink *st, struct netlink_client *client, struct buffer_if *buf) { + if (buf->size < (int)sizeof(struct iphdr)) { + Message(M_ERR,"%s: trying to deliver a too-short packet" + " from %s!\n",st->name, client?client->name:"(local)"); + BUF_FREE(buf); + return; + } + struct iphdr *iph=(struct iphdr *)buf->start; uint32_t dest=ntohl(iph->daddr); uint32_t source=ntohl(iph->saddr); @@ -511,9 +543,8 @@ static void netlink_packet_deliver(struct netlink *st, } else { if (best_quality>0) { /* XXX Fragment if required */ - st->routes[best_match]->deliver( - st->routes[best_match]->dst, buf); - st->routes[best_match]->outcount++; + netlink_client_deliver(st,st->routes[best_match], + source,dest,buf); BUF_ASSERT_FREE(buf); } else { /* Generate ICMP destination unreachable */ @@ -530,6 +561,7 @@ static void netlink_packet_forward(struct netlink *st, struct netlink_client *client, struct buffer_if *buf) { + if (buf->size < (int)sizeof(struct iphdr)) return; struct iphdr *iph=(struct iphdr *)buf->start; BUF_ASSERT_USED(buf); @@ -559,6 +591,12 @@ static void netlink_packet_local(struct netlink *st, st->localcount++; + if (buf->size < (int)sizeof(struct icmphdr)) { + Message(M_WARNING,"%s: short packet addressed to secnet; " + "ignoring it\n",st->name); + BUF_FREE(buf); + return; + } h=(struct icmphdr *)buf->start; if ((ntohs(h->iph.frag_off)&0xbfff)!=0) { @@ -603,15 +641,18 @@ static void netlink_incoming(struct netlink *st, struct netlink_client *client, uint32_t source,dest; struct iphdr *iph; char errmsgbuf[50]; + const char *sourcedesc=client?client->name:"host"; BUF_ASSERT_USED(buf); + if (!netlink_check(st,buf,errmsgbuf,sizeof(errmsgbuf))) { Message(M_WARNING,"%s: bad IP packet from %s: %s\n", - st->name,client?client->name:"host", + st->name,sourcedesc, errmsgbuf); BUF_FREE(buf); return; } + assert(buf->size >= (int)sizeof(struct icmphdr)); iph=(struct iphdr *)buf->start; source=ntohl(iph->saddr); @@ -658,7 +699,7 @@ static void netlink_incoming(struct netlink *st, struct netlink_client *client, if (client) { st->deliver_to_host(st->dst,buf); } else { - st->clients->deliver(st->clients->dst,buf); + netlink_client_deliver(st,st->clients,source,dest,buf); } BUF_ASSERT_FREE(buf); return; @@ -724,7 +765,7 @@ static void netlink_dump_routes(struct netlink *st, bool_t requested) if (requested) c=M_WARNING; if (st->ptp) { net=ipaddr_to_string(st->secnet_address); - Message(c,"%s: point-to-point (remote end is %s); routes:\n", + Message(c,"%s: point-to-point (remote end is %s); routes: ", st->name, net); free(net); netlink_output_subnets(st,c,st->clients->subnets); @@ -808,12 +849,10 @@ static void netlink_inst_set_mtu(void *sst, int32_t new_mtu) } static void netlink_inst_reg(void *sst, netlink_deliver_fn *deliver, - void *dst, int32_t max_start_pad) + void *dst) { struct netlink_client *c=sst; - struct netlink *st=c->nst; - if (max_start_pad > st->max_start_pad) st->max_start_pad=max_start_pad; c->deliver=deliver; c->dst=dst; } @@ -941,7 +980,6 @@ netlink_deliver_fn *netlink_init(struct netlink *st, st->cl.type=CL_PURE; st->cl.apply=netlink_inst_apply; st->cl.interface=st; - st->max_start_pad=0; st->clients=NULL; st->routes=NULL; st->n_clients=0;