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