X-Git-Url: https://git.distorted.org.uk/~mdw/secnet/blobdiff_plain/6e3fd952d7052293905334a3bb3911c775222ea6..091433c62a7e2fdb12f60d2468c5f98b9603f429:/netlink.c diff --git a/netlink.c b/netlink.c index 2c3d12d..954dbb6 100644 --- a/netlink.c +++ b/netlink.c @@ -237,6 +237,11 @@ struct icmphdr { static const union icmpinfofield icmp_noinfo; +static const char *sender_name(struct netlink_client *sender /* or NULL */) +{ + return sender?sender->name:"(local)"; +} + static void netlink_packet_deliver(struct netlink *st, struct netlink_client *client, struct buffer_if *buf); @@ -376,7 +381,9 @@ static uint16_t netlink_icmp_reply_len(struct buffer_if *buf) /* client indicates where the packet we're constructing a response to comes from. NULL indicates the host. */ -static void netlink_icmp_simple(struct netlink *st, struct buffer_if *buf, +static void netlink_icmp_simple(struct netlink *st, + struct netlink_client *origsender, + struct buffer_if *buf, uint8_t type, uint8_t code, union icmpinfofield info) { @@ -465,6 +472,7 @@ static const char *fragment_filter_header(uint8_t *base, long *hlp) /* Fragment or send ICMP Fragmentation Needed */ static void netlink_maybe_fragment(struct netlink *st, + struct netlink_client *sender, netlink_deliver_fn *deliver, void *deliver_dst, const char *delivery_name, @@ -496,7 +504,7 @@ static void netlink_maybe_fragment(struct netlink *st, if (orig_frag&IPHDR_FRAG_DONT) { union icmpinfofield info = { .fragneeded = { .unused = 0, .mtu = htons(mtu) } }; - netlink_icmp_simple(st,buf, + netlink_icmp_simple(st,sender,buf, ICMP_TYPE_UNREACHABLE, ICMP_CODE_FRAGMENTATION_REQUIRED, info); @@ -591,7 +599,7 @@ static void netlink_client_deliver(struct netlink *st, BUF_FREE(buf); return; } - netlink_maybe_fragment(st, client->deliver,client->dst,client->name, + netlink_maybe_fragment(st,NULL, client->deliver,client->dst,client->name, client->mtu, source,dest,buf); client->outcount++; } @@ -599,24 +607,24 @@ static void netlink_client_deliver(struct netlink *st, /* Deliver a packet to the host; used after we have decided that that * is what to do with it. */ static void netlink_host_deliver(struct netlink *st, + struct netlink_client *sender, uint32_t source, uint32_t dest, struct buffer_if *buf) { - netlink_maybe_fragment(st, st->deliver_to_host,st->dst,"(host)", + netlink_maybe_fragment(st,sender, st->deliver_to_host,st->dst,"(host)", st->mtu, source,dest,buf); st->outcount++; } -/* Deliver a packet. "client" is the _origin_ of the packet, not its - destination, and is NULL for packets from the host and packets +/* Deliver a packet. "sender"==NULL for packets from the host and packets generated internally in secnet. */ static void netlink_packet_deliver(struct netlink *st, - struct netlink_client *client, + struct netlink_client *sender, 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)"); + " from %s!\n",st->name, sender_name(sender)); BUF_FREE(buf); return; } @@ -638,9 +646,9 @@ static void netlink_packet_deliver(struct netlink *st, return; } - /* Packets from the host (client==NULL) may always be routed. Packets + /* Packets from the host (sender==NULL) may always be routed. Packets from clients with the allow_route option will also be routed. */ - if (!client || (client && (client->options & OPT_ALLOWROUTE))) + if (!sender || (sender && (sender->options & OPT_ALLOWROUTE))) allow_route=True; /* If !allow_route, we check the routing table anyway, and if @@ -686,7 +694,7 @@ static void netlink_packet_deliver(struct netlink *st, /* The packet's not going down a tunnel. It might (ought to) be for the host. */ if (ipset_contains_addr(st->networks,dest)) { - netlink_host_deliver(st,source,dest,buf); + netlink_host_deliver(st,sender,source,dest,buf); BUF_ASSERT_FREE(buf); } else { string_t s,d; @@ -695,7 +703,7 @@ static void netlink_packet_deliver(struct netlink *st, Message(M_DEBUG,"%s: don't know where to deliver packet " "(s=%s, d=%s)\n", st->name, s, d); free(s); free(d); - netlink_icmp_simple(st,buf,ICMP_TYPE_UNREACHABLE, + netlink_icmp_simple(st,sender,buf,ICMP_TYPE_UNREACHABLE, ICMP_CODE_NET_UNREACHABLE, icmp_noinfo); BUF_FREE(buf); } @@ -712,7 +720,7 @@ static void netlink_packet_deliver(struct netlink *st, st->name,s,d); free(s); free(d); - netlink_icmp_simple(st,buf,ICMP_TYPE_UNREACHABLE, + netlink_icmp_simple(st,sender,buf,ICMP_TYPE_UNREACHABLE, ICMP_CODE_NET_PROHIBITED, icmp_noinfo); BUF_FREE(buf); } else { @@ -722,7 +730,7 @@ static void netlink_packet_deliver(struct netlink *st, BUF_ASSERT_FREE(buf); } else { /* Generate ICMP destination unreachable */ - netlink_icmp_simple(st,buf, + netlink_icmp_simple(st,sender,buf, ICMP_TYPE_UNREACHABLE, ICMP_CODE_NET_UNREACHABLE, icmp_noinfo); @@ -734,7 +742,7 @@ static void netlink_packet_deliver(struct netlink *st, } static void netlink_packet_forward(struct netlink *st, - struct netlink_client *client, + struct netlink_client *sender, struct buffer_if *buf) { if (buf->size < (int)sizeof(struct iphdr)) return; @@ -745,7 +753,7 @@ static void netlink_packet_forward(struct netlink *st, /* Packet has already been checked */ if (iph->ttl<=1) { /* Generate ICMP time exceeded */ - netlink_icmp_simple(st,buf,ICMP_TYPE_TIME_EXCEEDED, + netlink_icmp_simple(st,sender,buf,ICMP_TYPE_TIME_EXCEEDED, ICMP_CODE_TTL_EXCEEDED,icmp_noinfo); BUF_FREE(buf); return; @@ -754,13 +762,13 @@ static void netlink_packet_forward(struct netlink *st, iph->check=0; iph->check=ip_fast_csum((uint8_t *)iph,iph->ihl); - netlink_packet_deliver(st,client,buf); + netlink_packet_deliver(st,sender,buf); BUF_ASSERT_FREE(buf); } /* Deal with packets addressed explicitly to us */ static void netlink_packet_local(struct netlink *st, - struct netlink_client *client, + struct netlink_client *sender, struct buffer_if *buf) { struct icmphdr *h; @@ -803,7 +811,7 @@ static void netlink_packet_local(struct netlink *st, Message(M_WARNING,"%s: unknown incoming ICMP\n",st->name); } else { /* Send ICMP protocol unreachable */ - netlink_icmp_simple(st,buf,ICMP_TYPE_UNREACHABLE, + netlink_icmp_simple(st,sender,buf,ICMP_TYPE_UNREACHABLE, ICMP_CODE_PROTOCOL_UNREACHABLE,icmp_noinfo); BUF_FREE(buf); return; @@ -814,13 +822,13 @@ static void netlink_packet_local(struct netlink *st, /* If cid==NULL packet is from host, otherwise cid specifies which tunnel it came from. */ -static void netlink_incoming(struct netlink *st, struct netlink_client *client, +static void netlink_incoming(struct netlink *st, struct netlink_client *sender, struct buffer_if *buf) { uint32_t source,dest; struct iphdr *iph; char errmsgbuf[50]; - const char *sourcedesc=client?client->name:"host"; + const char *sourcedesc=sender?sender->name:"host"; BUF_ASSERT_USED(buf); @@ -831,7 +839,7 @@ static void netlink_incoming(struct netlink *st, struct netlink_client *client, BUF_FREE(buf); return; } - assert(buf->size >= (int)sizeof(struct icmphdr)); + assert(buf->size >= (int)sizeof(struct iphdr)); iph=(struct iphdr *)buf->start; source=ntohl(iph->saddr); @@ -840,15 +848,15 @@ static void netlink_incoming(struct netlink *st, struct netlink_client *client, /* Check source. If we don't like the source, there's no point generating ICMP because we won't know how to get it to the source of the packet. */ - if (client) { + if (sender) { /* Check that the packet source is appropriate for the tunnel it came down */ - if (!ipset_contains_addr(client->networks,source)) { + if (!ipset_contains_addr(sender->networks,source)) { string_t s,d; s=ipaddr_to_string(source); d=ipaddr_to_string(dest); Message(M_WARNING,"%s: packet from tunnel %s with bad " - "source address (s=%s,d=%s)\n",st->name,client->name,s,d); + "source address (s=%s,d=%s)\n",st->name,sender->name,s,d); free(s); free(d); BUF_FREE(buf); return; @@ -875,8 +883,8 @@ static void netlink_incoming(struct netlink *st, struct netlink_client *client, where it came from. It's up to external software to check address validity and generate ICMP, etc. */ if (st->ptp) { - if (client) { - netlink_host_deliver(st,source,dest,buf); + if (sender) { + netlink_host_deliver(st,sender,source,dest,buf); } else { netlink_client_deliver(st,st->clients,source,dest,buf); } @@ -887,11 +895,11 @@ static void netlink_incoming(struct netlink *st, struct netlink_client *client, /* st->secnet_address needs checking before matching destination addresses */ if (dest==st->secnet_address) { - netlink_packet_local(st,client,buf); + netlink_packet_local(st,sender,buf); BUF_ASSERT_FREE(buf); return; } - netlink_packet_forward(st,client,buf); + netlink_packet_forward(st,sender,buf); BUF_ASSERT_FREE(buf); } @@ -1028,12 +1036,16 @@ 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) + void *dst, uint32_t *localmtu_r) { struct netlink_client *c=sst; + struct netlink *st=c->nst; c->deliver=deliver; c->dst=dst; + + if (localmtu_r) + *localmtu_r=st->mtu; } static struct flagstr netlink_option_table[]={ @@ -1186,6 +1198,8 @@ netlink_deliver_fn *netlink_init(struct netlink *st, st->remote_networks=ipset_complement(empty); ipset_free(empty); } + st->local_address=string_item_to_ipaddr( + dict_find_item(dict,"local-address", True, "netlink", loc),"netlink"); sa=dict_find_item(dict,"secnet-address",False,"netlink",loc); ptpa=dict_find_item(dict,"ptp-address",False,"netlink",loc);