chiark / gitweb /
f6d4e72920ab7b9a28422ae200353e4a231dcb24
[secnet.git] / netlink.c
1 /* User-kernel network link */
2
3 /* See RFCs 791, 792, 1123 and 1812 */
4
5 /* The netlink device is actually a router.  Tunnels are unnumbered
6    point-to-point lines (RFC1812 section 2.2.7); the router has a
7    single address (the 'router-id'). */
8
9 /* This is where we currently have the anti-spoofing paranoia - before
10    sending a packet to the kernel we check that the tunnel it came
11    over could reasonably have produced it. */
12
13
14 /* Points to note from RFC1812 (which may require changes in this
15    file):
16
17 3.3.4 Maximum Transmission Unit - MTU
18
19    The MTU of each logical interface MUST be configurable within the
20    range of legal MTUs for the interface.
21
22    Many Link Layer protocols define a maximum frame size that may be
23    sent.  In such cases, a router MUST NOT allow an MTU to be set which
24    would allow sending of frames larger than those allowed by the Link
25    Layer protocol.  However, a router SHOULD be willing to receive a
26    packet as large as the maximum frame size even if that is larger than
27    the MTU.
28
29 4.2.1  A router SHOULD count datagrams discarded.
30
31 4.2.2.1 Source route options - we probably should implement processing
32 of source routes, even though mostly the security policy will prevent
33 their use.
34
35 5.3.13.4 Source Route Options
36
37    A router MUST implement support for source route options in forwarded
38    packets.  A router MAY implement a configuration option that, when
39    enabled, causes all source-routed packets to be discarded.  However,
40    such an option MUST NOT be enabled by default.
41
42 5.3.13.5 Record Route Option
43
44    Routers MUST support the Record Route option in forwarded packets.
45
46    A router MAY provide a configuration option that, if enabled, will
47    cause the router to ignore (i.e., pass through unchanged) Record
48    Route options in forwarded packets.  If provided, such an option MUST
49    default to enabling the record-route.  This option should not affect
50    the processing of Record Route options in datagrams received by the
51    router itself (in particular, Record Route options in ICMP echo
52    requests will still be processed according to Section [4.3.3.6]).
53
54 5.3.13.6 Timestamp Option
55
56    Routers MUST support the timestamp option in forwarded packets.  A
57    timestamp value MUST follow the rules given [INTRO:2].
58
59    If the flags field = 3 (timestamp and prespecified address), the
60    router MUST add its timestamp if the next prespecified address
61    matches any of the router's IP addresses.  It is not necessary that
62    the prespecified address be either the address of the interface on
63    which the packet arrived or the address of the interface over which
64    it will be sent.
65
66
67 4.2.2.7 Fragmentation: RFC 791 Section 3.2
68
69    Fragmentation, as described in [INTERNET:1], MUST be supported by a
70    router.
71
72 4.2.2.8 Reassembly: RFC 791 Section 3.2
73
74    As specified in the corresponding section of [INTRO:2], a router MUST
75    support reassembly of datagrams that it delivers to itself.
76
77 4.2.2.9 Time to Live: RFC 791 Section 3.2
78
79    Note in particular that a router MUST NOT check the TTL of a packet
80    except when forwarding it.
81
82    A router MUST NOT discard a datagram just because it was received
83    with TTL equal to zero or one; if it is to the router and otherwise
84    valid, the router MUST attempt to receive it.
85
86    On messages the router originates, the IP layer MUST provide a means
87    for the transport layer to set the TTL field of every datagram that
88    is sent.  When a fixed TTL value is used, it MUST be configurable.
89
90
91 8.1 The Simple Network Management Protocol - SNMP
92 8.1.1 SNMP Protocol Elements
93
94    Routers MUST be manageable by SNMP [MGT:3].  The SNMP MUST operate
95    using UDP/IP as its transport and network protocols.
96
97
98 */
99
100 #include <string.h>
101 #include <assert.h>
102 #include <limits.h>
103 #include "secnet.h"
104 #include "util.h"
105 #include "ipaddr.h"
106 #include "netlink.h"
107 #include "process.h"
108
109 #define OPT_SOFTROUTE   1
110 #define OPT_ALLOWROUTE  2
111
112 #define ICMP_TYPE_ECHO_REPLY             0
113
114 #define ICMP_TYPE_UNREACHABLE            3
115 #define ICMP_CODE_NET_UNREACHABLE        0
116 #define ICMP_CODE_PROTOCOL_UNREACHABLE   2
117 #define ICMP_CODE_FRAGMENTATION_REQUIRED 4
118 #define ICMP_CODE_NET_PROHIBITED        13
119
120 #define ICMP_TYPE_ECHO_REQUEST           8
121
122 #define ICMP_TYPE_TIME_EXCEEDED         11
123 #define ICMP_CODE_TTL_EXCEEDED           0
124
125 /* Generic IP checksum routine */
126 static inline uint16_t ip_csum(uint8_t *iph,uint32_t count)
127 {
128     register uint32_t sum=0;
129
130     while (count>1) {
131         sum+=ntohs(*(uint16_t *)iph);
132         iph+=2;
133         count-=2;
134     }
135     if(count>0)
136         sum+=*(uint8_t *)iph;
137     while (sum>>16)
138         sum=(sum&0xffff)+(sum>>16);
139     return htons(~sum);
140 }
141
142 #ifdef i386
143 /*
144  *      This is a version of ip_compute_csum() optimized for IP headers,
145  *      which always checksum on 4 octet boundaries.
146  *
147  *      By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
148  *      Arnt Gulbrandsen.
149  */
150 static inline uint16_t ip_fast_csum(uint8_t *iph, uint32_t ihl) {
151     uint32_t sum;
152
153     __asm__ __volatile__(
154             "movl (%1), %0      ;\n"
155             "subl $4, %2        ;\n"
156             "jbe 2f             ;\n"
157             "addl 4(%1), %0     ;\n"
158             "adcl 8(%1), %0     ;\n"
159             "adcl 12(%1), %0    ;\n"
160 "1:         adcl 16(%1), %0     ;\n"
161             "lea 4(%1), %1      ;\n"
162             "decl %2            ;\n"
163             "jne 1b             ;\n"
164             "adcl $0, %0        ;\n"
165             "movl %0, %2        ;\n"
166             "shrl $16, %0       ;\n"
167             "addw %w2, %w0      ;\n"
168             "adcl $0, %0        ;\n"
169             "notl %0            ;\n"
170 "2:                             ;\n"
171         /* Since the input registers which are loaded with iph and ipl
172            are modified, we must also specify them as outputs, or gcc
173            will assume they contain their original values. */
174         : "=r" (sum), "=r" (iph), "=r" (ihl)
175         : "1" (iph), "2" (ihl)
176         : "memory");
177     return sum;
178 }
179 #else
180 static inline uint16_t ip_fast_csum(uint8_t *iph, uint32_t ihl)
181 {
182     return ip_csum(iph,ihl*4);
183 }
184 #endif
185
186 struct iphdr {
187 #if defined (WORDS_BIGENDIAN)
188     uint8_t    version:4,
189                ihl:4;
190 #else
191     uint8_t    ihl:4,
192                version:4;
193 #endif
194     uint8_t    tos;
195     uint16_t   tot_len;
196     uint16_t   id;
197     uint16_t   frag_off;
198     uint8_t    ttl;
199     uint8_t    protocol;
200     uint16_t   check;
201     uint32_t   saddr;
202     uint32_t   daddr;
203     /* The options start here. */
204 };
205
206 struct icmphdr {
207     struct iphdr iph;
208     uint8_t type;
209     uint8_t code;
210     uint16_t check;
211     union {
212         uint32_t unused;
213         struct {
214             uint8_t pointer;
215             uint8_t unused1;
216             uint16_t unused2;
217         } pprob;
218         uint32_t gwaddr;
219         struct {
220             uint16_t id;
221             uint16_t seq;
222         } echo;
223     } d;
224 };
225     
226 static void netlink_packet_deliver(struct netlink *st,
227                                    struct netlink_client *client,
228                                    struct buffer_if *buf);
229
230 /* XXX RFC1812 4.3.2.5:
231    All other ICMP error messages (Destination Unreachable,
232    Redirect, Time Exceeded, and Parameter Problem) SHOULD have their
233    precedence value set to 6 (INTERNETWORK CONTROL) or 7 (NETWORK
234    CONTROL).  The IP Precedence value for these error messages MAY be
235    settable.
236    */
237 static struct icmphdr *netlink_icmp_tmpl(struct netlink *st,
238                                          uint32_t dest,uint16_t len)
239 {
240     struct icmphdr *h;
241
242     BUF_ALLOC(&st->icmp,"netlink_icmp_tmpl");
243     buffer_init(&st->icmp,st->max_start_pad);
244     h=buf_append(&st->icmp,sizeof(*h));
245
246     h->iph.version=4;
247     h->iph.ihl=5;
248     h->iph.tos=0;
249     h->iph.tot_len=htons(len+(h->iph.ihl*4)+8);
250     h->iph.id=0;
251     h->iph.frag_off=0;
252     h->iph.ttl=255; /* XXX should be configurable */
253     h->iph.protocol=1;
254     h->iph.saddr=htonl(st->secnet_address);
255     h->iph.daddr=htonl(dest);
256     h->iph.check=0;
257     h->iph.check=ip_fast_csum((uint8_t *)&h->iph,h->iph.ihl);
258     h->check=0;
259     h->d.unused=0;
260
261     return h;
262 }
263
264 /* Fill in the ICMP checksum field correctly */
265 static void netlink_icmp_csum(struct icmphdr *h)
266 {
267     uint32_t len;
268
269     len=ntohs(h->iph.tot_len)-(4*h->iph.ihl);
270     h->check=0;
271     h->check=ip_csum(&h->type,len);
272 }
273
274 /* RFC1122:
275  *       An ICMP error message MUST NOT be sent as the result of
276  *       receiving:
277  *
278  *       *    an ICMP error message, or
279  *
280  *       *    a datagram destined to an IP broadcast or IP multicast
281  *            address, or
282  *
283  *       *    a datagram sent as a link-layer broadcast, or
284  *
285  *       *    a non-initial fragment, or
286  *
287  *       *    a datagram whose source address does not define a single
288  *            host -- e.g., a zero address, a loopback address, a
289  *            broadcast address, a multicast address, or a Class E
290  *            address.
291  */
292 static bool_t netlink_icmp_may_reply(struct buffer_if *buf)
293 {
294     struct iphdr *iph;
295     struct icmphdr *icmph;
296     uint32_t source;
297
298     iph=(struct iphdr *)buf->start;
299     icmph=(struct icmphdr *)buf->start;
300     if (iph->protocol==1) {
301         switch(icmph->type) {
302         case 3: /* Destination unreachable */
303         case 11: /* Time Exceeded */
304         case 12: /* Parameter Problem */
305             return False;
306         }
307     }
308     /* How do we spot broadcast destination addresses? */
309     if (ntohs(iph->frag_off)&0x1fff) return False; /* Non-initial fragment */
310     source=ntohl(iph->saddr);
311     if (source==0) return False;
312     if ((source&0xff000000)==0x7f000000) return False;
313     /* How do we spot broadcast source addresses? */
314     if ((source&0xf0000000)==0xe0000000) return False; /* Multicast */
315     if ((source&0xf0000000)==0xf0000000) return False; /* Class E */
316     return True;
317 }
318
319 /* How much of the original IP packet do we include in its ICMP
320    response? The header plus up to 64 bits. */
321
322 /* XXX TODO RFC1812:
323 4.3.2.3 Original Message Header
324
325    Historically, every ICMP error message has included the Internet
326    header and at least the first 8 data bytes of the datagram that
327    triggered the error.  This is no longer adequate, due to the use of
328    IP-in-IP tunneling and other technologies.  Therefore, the ICMP
329    datagram SHOULD contain as much of the original datagram as possible
330    without the length of the ICMP datagram exceeding 576 bytes.  The
331    returned IP header (and user data) MUST be identical to that which
332    was received, except that the router is not required to undo any
333    modifications to the IP header that are normally performed in
334    forwarding that were performed before the error was detected (e.g.,
335    decrementing the TTL, or updating options).  Note that the
336    requirements of Section [4.3.3.5] supersede this requirement in some
337    cases (i.e., for a Parameter Problem message, if the problem is in a
338    modified field, the router must undo the modification).  See Section
339    [4.3.3.5]).
340    */
341 static uint16_t netlink_icmp_reply_len(struct buffer_if *buf)
342 {
343     struct iphdr *iph=(struct iphdr *)buf->start;
344     uint16_t hlen,plen;
345
346     hlen=iph->ihl*4;
347     /* We include the first 8 bytes of the packet data, provided they exist */
348     hlen+=8;
349     plen=ntohs(iph->tot_len);
350     return (hlen>plen?plen:hlen);
351 }
352
353 /* client indicates where the packet we're constructing a response to
354    comes from. NULL indicates the host. */
355 static void netlink_icmp_simple(struct netlink *st, struct buffer_if *buf,
356                                 struct netlink_client *client,
357                                 uint8_t type, uint8_t code)
358 {
359     struct iphdr *iph=(struct iphdr *)buf->start;
360     struct icmphdr *h;
361     uint16_t len;
362
363     if (netlink_icmp_may_reply(buf)) {
364         len=netlink_icmp_reply_len(buf);
365         h=netlink_icmp_tmpl(st,ntohl(iph->saddr),len);
366         h->type=type; h->code=code;
367         memcpy(buf_append(&st->icmp,len),buf->start,len);
368         netlink_icmp_csum(h);
369         netlink_packet_deliver(st,NULL,&st->icmp);
370         BUF_ASSERT_FREE(&st->icmp);
371     }
372 }
373
374 /*
375  * RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the
376  * checksum.
377  * RFC1812: 4.2.2.5 MUST discard messages containing invalid checksums.
378  *
379  * Is the datagram acceptable?
380  *
381  * 1. Length at least the size of an ip header
382  * 2. Version of 4
383  * 3. Checksums correctly.
384  * 4. Doesn't have a bogus length
385  */
386 static bool_t netlink_check(struct netlink *st, struct buffer_if *buf)
387 {
388     struct iphdr *iph=(struct iphdr *)buf->start;
389     uint32_t len;
390
391     if (iph->ihl < 5 || iph->version != 4) return False;
392     if (buf->size < iph->ihl*4) return False;
393     if (ip_fast_csum((uint8_t *)iph, iph->ihl)!=0) return False;
394     len=ntohs(iph->tot_len);
395     /* There should be no padding */
396     if (buf->size!=len || len<(iph->ihl<<2)) return False;
397     /* XXX check that there's no source route specified */
398     return True;
399 }
400
401 /* Deliver a packet. "client" is the _origin_ of the packet, not its
402    destination, and is NULL for packets from the host and packets
403    generated internally in secnet.  */
404 static void netlink_packet_deliver(struct netlink *st,
405                                    struct netlink_client *client,
406                                    struct buffer_if *buf)
407 {
408     struct iphdr *iph=(struct iphdr *)buf->start;
409     uint32_t dest=ntohl(iph->daddr);
410     uint32_t source=ntohl(iph->saddr);
411     uint32_t best_quality;
412     bool_t allow_route=False;
413     bool_t found_allowed=False;
414     int best_match;
415     int i;
416
417     BUF_ASSERT_USED(buf);
418
419     if (dest==st->secnet_address) {
420         Message(M_ERR,"%s: trying to deliver a packet to myself!\n",st->name);
421         BUF_FREE(buf);
422         return;
423     }
424     
425     /* Packets from the host (client==NULL) may always be routed.  Packets
426        from clients with the allow_route option will also be routed. */
427     if (!client || (client && (client->options & OPT_ALLOWROUTE)))
428         allow_route=True;
429
430     /* If !allow_route, we check the routing table anyway, and if
431        there's a suitable route with OPT_ALLOWROUTE set we use it.  If
432        there's a suitable route, but none with OPT_ALLOWROUTE set then
433        we generate ICMP 'communication with destination network
434        administratively prohibited'. */
435
436     best_quality=0;
437     best_match=-1;
438     for (i=0; i<st->n_clients; i++) {
439         if (st->routes[i]->up &&
440             ipset_contains_addr(st->routes[i]->networks,dest)) {
441             /* It's an available route to the correct destination. But is
442                it better than the one we already have? */
443
444             /* If we have already found an allowed route then we don't
445                bother looking at routes we're not allowed to use.  If
446                we don't yet have an allowed route we'll consider any.  */
447             if (!allow_route && found_allowed) {
448                 if (!(st->routes[i]->options&OPT_ALLOWROUTE)) continue;
449             }
450             
451             if (st->routes[i]->link_quality>best_quality
452                 || best_quality==0) {
453                 best_quality=st->routes[i]->link_quality;
454                 best_match=i;
455                 if (st->routes[i]->options&OPT_ALLOWROUTE)
456                     found_allowed=True;
457                 /* If quality isn't perfect we may wish to
458                    consider kicking the tunnel with a 0-length
459                    packet to prompt it to perform a key setup.
460                    Then it'll eventually decide it's up or
461                    down. */
462                 /* If quality is perfect and we're allowed to use the
463                    route we don't need to search any more. */
464                 if (best_quality>=MAXIMUM_LINK_QUALITY && 
465                     (allow_route || found_allowed)) break;
466             }
467         }
468     }
469     if (best_match==-1) {
470         /* The packet's not going down a tunnel.  It might (ought to)
471            be for the host.   */
472         if (ipset_contains_addr(st->networks,dest)) {
473             st->deliver_to_host(st->dst,buf);
474             st->outcount++;
475             BUF_ASSERT_FREE(buf);
476         } else {
477             string_t s,d;
478             s=ipaddr_to_string(source);
479             d=ipaddr_to_string(dest);
480             Message(M_DEBUG,"%s: don't know where to deliver packet "
481                     "(s=%s, d=%s)\n", st->name, s, d);
482             free(s); free(d);
483             netlink_icmp_simple(st,buf,client,ICMP_TYPE_UNREACHABLE,
484                                 ICMP_CODE_NET_UNREACHABLE);
485             BUF_FREE(buf);
486         }
487     } else {
488         if (!allow_route &&
489             !(st->routes[best_match]->options&OPT_ALLOWROUTE)) {
490             string_t s,d;
491             s=ipaddr_to_string(source);
492             d=ipaddr_to_string(dest);
493             /* We have a usable route but aren't allowed to use it.
494                Generate ICMP destination unreachable: communication
495                with destination network administratively prohibited */
496             Message(M_NOTICE,"%s: denied forwarding for packet (s=%s, d=%s)\n",
497                     st->name,s,d);
498             free(s); free(d);
499                     
500             netlink_icmp_simple(st,buf,client,ICMP_TYPE_UNREACHABLE,
501                                 ICMP_CODE_NET_PROHIBITED);
502             BUF_FREE(buf);
503         } else {
504             if (best_quality>0) {
505                 /* XXX Fragment if required */
506                 st->routes[best_match]->deliver(
507                     st->routes[best_match]->dst, buf);
508                 st->routes[best_match]->outcount++;
509                 BUF_ASSERT_FREE(buf);
510             } else {
511                 /* Generate ICMP destination unreachable */
512                 netlink_icmp_simple(st,buf,client,ICMP_TYPE_UNREACHABLE,
513                                     ICMP_CODE_NET_UNREACHABLE); /* client==NULL */
514                 BUF_FREE(buf);
515             }
516         }
517     }
518     BUF_ASSERT_FREE(buf);
519 }
520
521 static void netlink_packet_forward(struct netlink *st, 
522                                    struct netlink_client *client,
523                                    struct buffer_if *buf)
524 {
525     struct iphdr *iph=(struct iphdr *)buf->start;
526     
527     BUF_ASSERT_USED(buf);
528
529     /* Packet has already been checked */
530     if (iph->ttl<=1) {
531         /* Generate ICMP time exceeded */
532         netlink_icmp_simple(st,buf,client,ICMP_TYPE_TIME_EXCEEDED,
533                             ICMP_CODE_TTL_EXCEEDED);
534         BUF_FREE(buf);
535         return;
536     }
537     iph->ttl--;
538     iph->check=0;
539     iph->check=ip_fast_csum((uint8_t *)iph,iph->ihl);
540
541     netlink_packet_deliver(st,client,buf);
542     BUF_ASSERT_FREE(buf);
543 }
544
545 /* Deal with packets addressed explicitly to us */
546 static void netlink_packet_local(struct netlink *st,
547                                  struct netlink_client *client,
548                                  struct buffer_if *buf)
549 {
550     struct icmphdr *h;
551
552     st->localcount++;
553
554     h=(struct icmphdr *)buf->start;
555
556     if ((ntohs(h->iph.frag_off)&0xbfff)!=0) {
557         Message(M_WARNING,"%s: fragmented packet addressed to secnet; "
558                 "ignoring it\n",st->name);
559         BUF_FREE(buf);
560         return;
561     }
562
563     if (h->iph.protocol==1) {
564         /* It's ICMP */
565         if (h->type==ICMP_TYPE_ECHO_REQUEST && h->code==0) {
566             /* ICMP echo-request. Special case: we re-use the buffer
567                to construct the reply. */
568             h->type=ICMP_TYPE_ECHO_REPLY;
569             h->iph.daddr=h->iph.saddr;
570             h->iph.saddr=htonl(st->secnet_address);
571             h->iph.ttl=255;
572             h->iph.check=0;
573             h->iph.check=ip_fast_csum((uint8_t *)h,h->iph.ihl);
574             netlink_icmp_csum(h);
575             netlink_packet_deliver(st,NULL,buf);
576             return;
577         }
578         Message(M_WARNING,"%s: unknown incoming ICMP\n",st->name);
579     } else {
580         /* Send ICMP protocol unreachable */
581         netlink_icmp_simple(st,buf,client,ICMP_TYPE_UNREACHABLE,
582                             ICMP_CODE_PROTOCOL_UNREACHABLE);
583         BUF_FREE(buf);
584         return;
585     }
586
587     BUF_FREE(buf);
588 }
589
590 /* If cid==NULL packet is from host, otherwise cid specifies which tunnel 
591    it came from. */
592 static void netlink_incoming(struct netlink *st, struct netlink_client *client,
593                              struct buffer_if *buf)
594 {
595     uint32_t source,dest;
596     struct iphdr *iph;
597
598     BUF_ASSERT_USED(buf);
599     if (!netlink_check(st,buf)) {
600         Message(M_WARNING,"%s: bad IP packet from %s\n",
601                 st->name,client?client->name:"host");
602         BUF_FREE(buf);
603         return;
604     }
605     iph=(struct iphdr *)buf->start;
606
607     source=ntohl(iph->saddr);
608     dest=ntohl(iph->daddr);
609
610     /* Check source. If we don't like the source, there's no point
611        generating ICMP because we won't know how to get it to the
612        source of the packet. */
613     if (client) {
614         /* Check that the packet source is appropriate for the tunnel
615            it came down */
616         if (!ipset_contains_addr(client->networks,source)) {
617             string_t s,d;
618             s=ipaddr_to_string(source);
619             d=ipaddr_to_string(dest);
620             Message(M_WARNING,"%s: packet from tunnel %s with bad "
621                     "source address (s=%s,d=%s)\n",st->name,client->name,s,d);
622             free(s); free(d);
623             BUF_FREE(buf);
624             return;
625         }
626     } else {
627         /* Check that the packet originates in our configured local
628            network, and hasn't been forwarded from elsewhere or
629            generated with the wrong source address */
630         if (!ipset_contains_addr(st->networks,source)) {
631             string_t s,d;
632             s=ipaddr_to_string(source);
633             d=ipaddr_to_string(dest);
634             Message(M_WARNING,"%s: outgoing packet with bad source address "
635                     "(s=%s,d=%s)\n",st->name,s,d);
636             free(s); free(d);
637             BUF_FREE(buf);
638             return;
639         }
640     }
641
642     /* If this is a point-to-point device we don't examine the
643        destination address at all; we blindly send it down our
644        one-and-only registered tunnel, or to the host, depending on
645        where it came from.  It's up to external software to check
646        address validity and generate ICMP, etc. */
647     if (st->ptp) {
648         if (client) {
649             st->deliver_to_host(st->dst,buf);
650         } else {
651             st->clients->deliver(st->clients->dst,buf);
652         }
653         BUF_ASSERT_FREE(buf);
654         return;
655     }
656
657     /* st->secnet_address needs checking before matching destination
658        addresses */
659     if (dest==st->secnet_address) {
660         netlink_packet_local(st,client,buf);
661         BUF_ASSERT_FREE(buf);
662         return;
663     }
664     netlink_packet_forward(st,client,buf);
665     BUF_ASSERT_FREE(buf);
666 }
667
668 static void netlink_inst_incoming(void *sst, struct buffer_if *buf)
669 {
670     struct netlink_client *c=sst;
671     struct netlink *st=c->nst;
672
673     netlink_incoming(st,c,buf);
674 }
675
676 static void netlink_dev_incoming(void *sst, struct buffer_if *buf)
677 {
678     struct netlink *st=sst;
679
680     netlink_incoming(st,NULL,buf);
681 }
682
683 static void netlink_set_quality(void *sst, uint32_t quality)
684 {
685     struct netlink_client *c=sst;
686     struct netlink *st=c->nst;
687
688     c->link_quality=quality;
689     c->up=(c->link_quality==LINK_QUALITY_DOWN)?False:True;
690     if (c->options&OPT_SOFTROUTE) {
691         st->set_routes(st->dst,c);
692     }
693 }
694
695 static void netlink_output_subnets(struct netlink *st, uint32_t loglevel,
696                                    struct subnet_list *snets)
697 {
698     uint32_t i;
699     string_t net;
700
701     for (i=0; i<snets->entries; i++) {
702         net=subnet_to_string(snets->list[i]);
703         Message(loglevel,"%s ",net);
704         free(net);
705     }
706 }
707
708 static void netlink_dump_routes(struct netlink *st, bool_t requested)
709 {
710     int i;
711     string_t net;
712     uint32_t c=M_INFO;
713
714     if (requested) c=M_WARNING;
715     if (st->ptp) {
716         net=ipaddr_to_string(st->secnet_address);
717         Message(c,"%s: point-to-point (remote end is %s); routes:\n",
718                 st->name, net);
719         free(net);
720         netlink_output_subnets(st,c,st->clients->subnets);
721         Message(c,"\n");
722     } else {
723         Message(c,"%s: routing table:\n",st->name);
724         for (i=0; i<st->n_clients; i++) {
725             netlink_output_subnets(st,c,st->routes[i]->subnets);
726             Message(c,"-> tunnel %s (%s,mtu %d,%s routes,%s,"
727                     "quality %d,use %d,pri %lu)\n",
728                     st->routes[i]->name,
729                     st->routes[i]->up?"up":"down",
730                     st->routes[i]->mtu,
731                     st->routes[i]->options&OPT_SOFTROUTE?"soft":"hard",
732                     st->routes[i]->options&OPT_ALLOWROUTE?"free":"restricted",
733                     st->routes[i]->link_quality,
734                     st->routes[i]->outcount,
735                     (unsigned long)st->routes[i]->priority);
736         }
737         net=ipaddr_to_string(st->secnet_address);
738         Message(c,"%s/32 -> netlink \"%s\" (use %d)\n",
739                 net,st->name,st->localcount);
740         free(net);
741         for (i=0; i<st->subnets->entries; i++) {
742             net=subnet_to_string(st->subnets->list[i]);
743             Message(c,"%s ",net);
744             free(net);
745         }
746         if (i>0)
747             Message(c,"-> host (use %d)\n",st->outcount);
748     }
749 }
750
751 /* ap is a pointer to a member of the routes array */
752 static int netlink_compare_client_priority(const void *ap, const void *bp)
753 {
754     const struct netlink_client *const*a=ap;
755     const struct netlink_client *const*b=bp;
756
757     if ((*a)->priority==(*b)->priority) return 0;
758     if ((*a)->priority<(*b)->priority) return 1;
759     return -1;
760 }
761
762 static void netlink_phase_hook(void *sst, uint32_t new_phase)
763 {
764     struct netlink *st=sst;
765     struct netlink_client *c;
766     uint32_t i;
767
768     /* All the networks serviced by the various tunnels should now
769      * have been registered.  We build a routing table by sorting the
770      * clients by priority.  */
771     st->routes=safe_malloc(st->n_clients*sizeof(*st->routes),
772                            "netlink_phase_hook");
773     /* Fill the table */
774     i=0;
775     for (c=st->clients; c; c=c->next) {
776         assert(i<INT_MAX);
777         st->routes[i++]=c;
778     }
779     /* Sort the table in descending order of priority */
780     qsort(st->routes,st->n_clients,sizeof(*st->routes),
781           netlink_compare_client_priority);
782
783     netlink_dump_routes(st,False);
784 }
785
786 static void netlink_signal_handler(void *sst, int signum)
787 {
788     struct netlink *st=sst;
789     Message(M_INFO,"%s: route dump requested by SIGUSR1\n",st->name);
790     netlink_dump_routes(st,True);
791 }
792
793 static void netlink_inst_output_config(void *sst, struct buffer_if *buf)
794 {
795 /*    struct netlink_client *c=sst; */
796 /*    struct netlink *st=c->nst; */
797
798     /* For now we don't output anything */
799     BUF_ASSERT_USED(buf);
800 }
801
802 static bool_t netlink_inst_check_config(void *sst, struct buffer_if *buf)
803 {
804 /*    struct netlink_client *c=sst; */
805 /*    struct netlink *st=c->nst; */
806
807     BUF_ASSERT_USED(buf);
808     /* We need to eat all of the configuration information from the buffer
809        for backward compatibility. */
810     buf->size=0;
811     return True;
812 }
813
814 static void netlink_inst_set_mtu(void *sst, uint32_t new_mtu)
815 {
816     struct netlink_client *c=sst;
817
818     c->mtu=new_mtu;
819 }
820
821 static void netlink_inst_reg(void *sst, netlink_deliver_fn *deliver, 
822                              void *dst, uint32_t max_start_pad,
823                              uint32_t max_end_pad)
824 {
825     struct netlink_client *c=sst;
826     struct netlink *st=c->nst;
827
828     if (max_start_pad > st->max_start_pad) st->max_start_pad=max_start_pad;
829     if (max_end_pad > st->max_end_pad) st->max_end_pad=max_end_pad;
830     c->deliver=deliver;
831     c->dst=dst;
832 }
833
834 static struct flagstr netlink_option_table[]={
835     { "soft", OPT_SOFTROUTE },
836     { "allow-route", OPT_ALLOWROUTE },
837     { NULL, 0}
838 };
839 /* This is the routine that gets called when the closure that's
840    returned by an invocation of a netlink device closure (eg. tun,
841    userv-ipif) is invoked.  It's used to create routes and pass in
842    information about them; the closure it returns is used by site
843    code.  */
844 static closure_t *netlink_inst_create(struct netlink *st,
845                                       struct cloc loc, dict_t *dict)
846 {
847     struct netlink_client *c;
848     string_t name;
849     struct ipset *networks;
850     uint32_t options,priority,mtu;
851     list_t *l;
852
853     name=dict_read_string(dict, "name", True, st->name, loc);
854
855     l=dict_lookup(dict,"routes");
856     if (!l)
857         cfgfatal(loc,st->name,"required parameter \"routes\" not found\n");
858     networks=string_list_to_ipset(l,loc,st->name,"routes");
859     options=string_list_to_word(dict_lookup(dict,"options"),
860                                 netlink_option_table,st->name);
861
862     priority=dict_read_number(dict,"priority",False,st->name,loc,0);
863     mtu=dict_read_number(dict,"mtu",False,st->name,loc,0);
864
865     if ((options&OPT_SOFTROUTE) && !st->set_routes) {
866         cfgfatal(loc,st->name,"this netlink device does not support "
867                  "soft routes.\n");
868         return NULL;
869     }
870
871     if (options&OPT_SOFTROUTE) {
872         /* XXX for now we assume that soft routes require root privilege;
873            this may not always be true. The device driver can tell us. */
874         require_root_privileges=True;
875         require_root_privileges_explanation="netlink: soft routes";
876         if (st->ptp) {
877             cfgfatal(loc,st->name,"point-to-point netlinks do not support "
878                      "soft routes.\n");
879             return NULL;
880         }
881     }
882
883     /* Check that nets are a subset of st->remote_networks;
884        refuse to register if they are not. */
885     if (!ipset_is_subset(st->remote_networks,networks)) {
886         cfgfatal(loc,st->name,"routes are not allowed\n");
887         return NULL;
888     }
889
890     c=safe_malloc(sizeof(*c),"netlink_inst_create");
891     c->cl.description=name;
892     c->cl.type=CL_NETLINK;
893     c->cl.apply=NULL;
894     c->cl.interface=&c->ops;
895     c->ops.st=c;
896     c->ops.reg=netlink_inst_reg;
897     c->ops.deliver=netlink_inst_incoming;
898     c->ops.set_quality=netlink_set_quality;
899     c->ops.output_config=netlink_inst_output_config;
900     c->ops.check_config=netlink_inst_check_config;
901     c->ops.set_mtu=netlink_inst_set_mtu;
902     c->nst=st;
903
904     c->networks=networks;
905     c->subnets=ipset_to_subnet_list(networks);
906     c->priority=priority;
907     c->deliver=NULL;
908     c->dst=NULL;
909     c->name=name;
910     c->link_quality=LINK_QUALITY_DOWN;
911     c->mtu=mtu?mtu:st->mtu;
912     c->options=options;
913     c->outcount=0;
914     c->up=False;
915     c->kup=False;
916     c->next=st->clients;
917     st->clients=c;
918     assert(st->n_clients < INT_MAX);
919     st->n_clients++;
920
921     return &c->cl;
922 }
923
924 static list_t *netlink_inst_apply(closure_t *self, struct cloc loc,
925                                   dict_t *context, list_t *args)
926 {
927     struct netlink *st=self->interface;
928
929     dict_t *dict;
930     item_t *item;
931     closure_t *cl;
932
933     item=list_elem(args,0);
934     if (!item || item->type!=t_dict) {
935         cfgfatal(loc,st->name,"must have a dictionary argument\n");
936     }
937     dict=item->data.dict;
938
939     cl=netlink_inst_create(st,loc,dict);
940
941     return new_closure(cl);
942 }
943
944 netlink_deliver_fn *netlink_init(struct netlink *st,
945                                  void *dst, struct cloc loc,
946                                  dict_t *dict, cstring_t description,
947                                  netlink_route_fn *set_routes,
948                                  netlink_deliver_fn *to_host)
949 {
950     item_t *sa, *ptpa;
951     list_t *l;
952
953     st->dst=dst;
954     st->cl.description=description;
955     st->cl.type=CL_PURE;
956     st->cl.apply=netlink_inst_apply;
957     st->cl.interface=st;
958     st->max_start_pad=0;
959     st->max_end_pad=0;
960     st->clients=NULL;
961     st->routes=NULL;
962     st->n_clients=0;
963     st->set_routes=set_routes;
964     st->deliver_to_host=to_host;
965
966     st->name=dict_read_string(dict,"name",False,description,loc);
967     if (!st->name) st->name=description;
968     l=dict_lookup(dict,"networks");
969     if (l) 
970         st->networks=string_list_to_ipset(l,loc,st->name,"networks");
971     else {
972         struct ipset *empty;
973         empty=ipset_new();
974         st->networks=ipset_complement(empty);
975         ipset_free(empty);
976     }
977     l=dict_lookup(dict,"remote-networks");
978     if (l) {
979         st->remote_networks=string_list_to_ipset(l,loc,st->name,
980                                                  "remote-networks");
981     } else {
982         struct ipset *empty;
983         empty=ipset_new();
984         st->remote_networks=ipset_complement(empty);
985         ipset_free(empty);
986     }
987
988     sa=dict_find_item(dict,"secnet-address",False,"netlink",loc);
989     ptpa=dict_find_item(dict,"ptp-address",False,"netlink",loc);
990     if (sa && ptpa) {
991         cfgfatal(loc,st->name,"you may not specify secnet-address and "
992                  "ptp-address in the same netlink device\n");
993     }
994     if (!(sa || ptpa)) {
995         cfgfatal(loc,st->name,"you must specify secnet-address or "
996                  "ptp-address for this netlink device\n");
997     }
998     if (sa) {
999         st->secnet_address=string_item_to_ipaddr(sa,"netlink");
1000         st->ptp=False;
1001     } else {
1002         st->secnet_address=string_item_to_ipaddr(ptpa,"netlink");
1003         st->ptp=True;
1004     }
1005     /* To be strictly correct we could subtract secnet_address from
1006        networks here.  It shouldn't make any practical difference,
1007        though, and will make the route dump look complicated... */
1008     st->subnets=ipset_to_subnet_list(st->networks);
1009     st->mtu=dict_read_number(dict, "mtu", False, "netlink", loc, DEFAULT_MTU);
1010     buffer_new(&st->icmp,ICMP_BUFSIZE);
1011     st->outcount=0;
1012     st->localcount=0;
1013
1014     add_hook(PHASE_SETUP,netlink_phase_hook,st);
1015     request_signal_notification(SIGUSR1, netlink_signal_handler, st);
1016
1017     /* If we're point-to-point then we return a CL_NETLINK directly,
1018        rather than a CL_NETLINK_OLD or pure closure (depending on
1019        compatibility).  This CL_NETLINK is for our one and only
1020        client.  Our cl.apply function is NULL. */
1021     if (st->ptp) {
1022         closure_t *cl;
1023         cl=netlink_inst_create(st,loc,dict);
1024         st->cl=*cl;
1025     }
1026     return netlink_dev_incoming;
1027 }
1028
1029 /* No connection to the kernel at all... */
1030
1031 struct null {
1032     struct netlink nl;
1033 };
1034
1035 static bool_t null_set_route(void *sst, struct netlink_client *routes)
1036 {
1037     struct null *st=sst;
1038
1039     if (routes->up!=routes->kup) {
1040         Message(M_INFO,"%s: setting routes for tunnel %s to state %s\n",
1041                 st->nl.name,routes->name,
1042                 routes->up?"up":"down");
1043         routes->kup=routes->up;
1044         return True;
1045     }
1046     return False;
1047 }
1048             
1049 static void null_deliver(void *sst, struct buffer_if *buf)
1050 {
1051     return;
1052 }
1053
1054 static list_t *null_apply(closure_t *self, struct cloc loc, dict_t *context,
1055                           list_t *args)
1056 {
1057     struct null *st;
1058     item_t *item;
1059     dict_t *dict;
1060
1061     st=safe_malloc(sizeof(*st),"null_apply");
1062
1063     item=list_elem(args,0);
1064     if (!item || item->type!=t_dict)
1065         cfgfatal(loc,"null-netlink","parameter must be a dictionary\n");
1066     
1067     dict=item->data.dict;
1068
1069     netlink_init(&st->nl,st,loc,dict,"null-netlink",null_set_route,
1070                  null_deliver);
1071
1072     return new_closure(&st->nl.cl);
1073 }
1074
1075 void netlink_module(dict_t *dict)
1076 {
1077     add_closure(dict,"null-netlink",null_apply);
1078 }