]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/net/if_spppfr.c
pf: mark removed connections within a multihome association as shutting down
[FreeBSD/FreeBSD.git] / sys / net / if_spppfr.c
1 /*-
2  * Synchronous Frame Relay link level subroutines.
3  * ANSI T1.617-compaible link management signaling
4  * implemented for Frame Relay mode.
5  * Cisco-type Frame Relay framing added, thanks Alex Tutubalin.
6  * Only one DLCI per channel for now.
7  *
8  * Copyright (C) 1994-2000 Cronyx Engineering.
9  * Author: Serge Vakulenko, <vak@cronyx.ru>
10  *
11  * Copyright (C) 1999-2004 Cronyx Engineering.
12  * Author: Kurakin Roman, <rik@cronyx.ru>
13  *
14  * This software is distributed with NO WARRANTIES, not even the implied
15  * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * Authors grant any other persons or organisations a permission to use,
18  * modify and redistribute this software in source and binary forms,
19  * as long as this message is kept with the software, all derivative
20  * works or modified versions.
21  *
22  * $Cronyx Id: if_spppfr.c,v 1.1.2.10 2004/06/29 09:02:30 rik Exp $
23  */
24
25 #include <sys/param.h>
26
27 #if defined(__FreeBSD__)
28 #include "opt_inet.h"
29 #include "opt_inet6.h"
30 #endif
31
32 #ifdef NetBSD1_3
33 #  if NetBSD1_3 > 6
34 #      include "opt_inet.h"
35 #      include "opt_inet6.h"
36 #      include "opt_iso.h"
37 #  endif
38 #endif
39
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/module.h>
43 #include <sys/sockio.h>
44 #include <sys/socket.h>
45 #include <sys/syslog.h>
46 #if defined(__FreeBSD__)
47 #include <sys/random.h>
48 #endif
49 #include <sys/malloc.h>
50 #include <sys/mbuf.h>
51
52 #if defined (__OpenBSD__)
53 #include <sys/md5k.h>
54 #else
55 #include <sys/md5.h>
56 #endif
57
58 #include <net/if.h>
59 #include <net/if_var.h>
60 #include <net/netisr.h>
61 #include <net/if_types.h>
62 #include <net/route.h>
63 #include <netinet/in.h>
64 #include <netinet/in_systm.h>
65 #include <netinet/ip.h>
66 #include <net/slcompress.h>
67
68 #if defined (__NetBSD__) || defined (__OpenBSD__)
69 #include <machine/cpu.h> /* XXX for softnet */
70 #endif
71
72 #include <machine/stdarg.h>
73
74 #include <netinet/in_var.h>
75 #ifdef INET
76 #include <netinet/ip.h>
77 #include <netinet/tcp.h>
78 #endif
79
80 #if defined (__FreeBSD__) || defined (__OpenBSD__)
81 #  include <netinet/if_ether.h>
82 #else
83 #  include <net/ethertypes.h>
84 #endif
85
86 #include <net/if_sppp.h>
87
88 /*
89  * Frame Relay.
90  */
91 #define FR_UI           0x03    /* Unnumbered Information */
92 #define FR_IP           0xCC    /* IP protocol identifier */
93 #define FR_PADDING      0x00    /* NLPID padding */
94 #define FR_SIGNALING    0x08    /* Q.933/T1.617 signaling identifier */
95 #define FR_SNAP         0x80    /* NLPID snap */
96
97 /*
98  * Header flags.
99  */
100 #define FR_DE           0x02    /* discard eligibility */
101 #define FR_FECN         0x04    /* forward notification */
102 #define FR_BECN         0x08    /* backward notification */
103
104 /*
105  * Signaling message types.
106  */
107 #define FR_MSG_ENQUIRY  0x75    /* status enquiry */
108 #define FR_MSG_STATUS   0x7d    /* status */
109
110 #define FR_ENQUIRY_SIZE 14
111
112 /*
113  * Message field types.
114  */
115 #define FR_FLD_RTYPE    0x01    /* report type */
116 #define FR_FLD_VERIFY   0x03    /* link verification */
117 #define FR_FLD_PVC      0x07    /* PVC status */
118 #define FR_FLD_LSHIFT5  0x95    /* locking shift 5 */
119
120 /*
121  * Report types.
122  */
123 #define FR_RTYPE_FULL   0       /* full status */
124 #define FR_RTYPE_SHORT  1       /* link verification only */
125 #define FR_RTYPE_SINGLE 2       /* single PVC status */
126
127 /* PVC status field. */
128 #define FR_DLCI_DELETE  0x04    /* PVC is deleted */
129 #define FR_DLCI_ACTIVE  0x02    /* PVC is operational */
130 #define FR_DLCI_NEW     0x08    /* PVC is new */
131
132 struct arp_req {
133         unsigned short  htype;          /* hardware type = ARPHRD_FRELAY */
134         unsigned short  ptype;          /* protocol type = ETHERTYPE_IP */
135         unsigned char   halen;          /* hardware address length = 2 */
136         unsigned char   palen;          /* protocol address length = 4 */
137         unsigned short  op;             /* ARP/RARP/InARP request/reply */
138         unsigned short  hsource;        /* hardware source address */
139         unsigned short  psource1;       /* protocol source */
140         unsigned short  psource2;
141         unsigned short  htarget;        /* hardware target address */
142         unsigned short  ptarget1;       /* protocol target */
143         unsigned short  ptarget2;
144 } __packed;
145
146 #if defined(__FreeBSD__) && __FreeBSD_version < 501113
147 #define SPP_FMT         "%s%d: "
148 #define SPP_ARGS(ifp)   (ifp)->if_name, (ifp)->if_unit
149 #else
150 #define SPP_FMT         "%s: "
151 #define SPP_ARGS(ifp)   (ifp)->if_xname
152 #endif
153
154 /* almost every function needs these */
155 #define STDDCL                                                  \
156         struct ifnet *ifp = SP2IFP(sp);                         \
157         int debug = ifp->if_flags & IFF_DEBUG
158
159 static void sppp_fr_arp (struct sppp *sp, struct arp_req *req, u_short addr);
160 static void sppp_fr_signal (struct sppp *sp, unsigned char *h, int len);
161
162 void sppp_fr_input (struct sppp *sp, struct mbuf *m)
163 {
164         STDDCL;
165         u_char *h = mtod (m, u_char*);
166         int isr = -1;
167         int dlci, hlen, proto;
168
169         /* Get the DLCI number. */
170         if (m->m_pkthdr.len < 10) {
171 bad:            m_freem (m);
172                 return;
173         }
174         dlci = (h[0] << 2 & 0x3f0) | (h[1] >> 4 & 0x0f);
175
176         /* Process signaling packets. */
177         if (dlci == 0) {
178                 sppp_fr_signal (sp, h, m->m_pkthdr.len);
179                 m_freem (m);
180                 return;
181         }
182
183         if (dlci != sp->fr_dlci) {
184                 if (debug)
185                         printf (SPP_FMT "Received packet from invalid DLCI %d\n",
186                                 SPP_ARGS(ifp), dlci);
187                 goto bad;
188         }
189
190         /* Process the packet. */
191         if (ntohs (*(short*) (h+2)) == ETHERTYPE_IP) {
192                 /* Prehistoric IP framing? */
193                 h[2] = FR_UI;
194                 h[3] = FR_IP;
195         }
196         if (h[2] != FR_UI) {
197                 if (debug)
198                         printf (SPP_FMT "Invalid frame relay header flag 0x%02x\n",
199                                 SPP_ARGS(ifp), h[2]);
200                 goto bad;
201         }
202         switch (h[3]) {
203         default:
204                 if (debug)
205                         printf (SPP_FMT "Unsupported NLPID 0x%02x\n",
206                                 SPP_ARGS(ifp), h[3]);
207                 goto bad;
208
209         case FR_PADDING:
210                 if (h[4] != FR_SNAP) {
211                         if (debug)
212                                 printf (SPP_FMT "Bad NLPID 0x%02x\n",
213                                         SPP_ARGS(ifp), h[4]);
214                         goto bad;
215                 }
216                 if (h[5] || h[6] || h[7]) {
217                         if (debug)
218                                 printf (SPP_FMT "Bad OID 0x%02x-0x%02x-0x%02x\n",
219                                         SPP_ARGS(ifp),
220                                         h[5], h[6], h[7]);
221                         goto bad;
222                 }
223                 proto = ntohs (*(short*) (h+8));
224                 if (proto == ETHERTYPE_ARP) {
225                         /* Process the ARP request. */
226                         if (m->m_pkthdr.len != 10 + sizeof (struct arp_req)) {
227                                 if (debug)
228                                         printf (SPP_FMT "Bad ARP request size = %d bytes\n",
229                                                 SPP_ARGS(ifp),
230                                                 m->m_pkthdr.len);
231                                 goto bad;
232                         }
233                         sppp_fr_arp (sp, (struct arp_req*) (h + 10),
234                                 h[0] << 8 | h[1]);
235                         m_freem (m);
236                         return;
237                 }
238                 hlen = 10;
239                 break;
240
241         case FR_IP:
242                 proto = ETHERTYPE_IP;
243                 hlen = 4;
244                 break;
245         }
246
247         /* Remove frame relay header. */
248         m_adj (m, hlen);
249
250         switch (proto) {
251         default:
252                 if_inc_counter(ifp, IFCOUNTER_NOPROTO, 1);
253 drop:           if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
254                 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
255                 m_freem (m);
256                 return;
257 #ifdef INET
258         case ETHERTYPE_IP:
259                 isr = NETISR_IP;
260                 break;
261 #endif
262         }
263
264         if (! (ifp->if_flags & IFF_UP))
265                 goto drop;
266
267         M_SETFIB(m, ifp->if_fib);
268
269         /* Check queue. */
270         if (netisr_queue(isr, m)) {     /* (0) on success. */
271                 if (debug)
272                         log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n",
273                                 SPP_ARGS(ifp));
274         }
275 }
276
277 /*
278  * Add the frame relay header to the packet.
279  * For IP the header length is 4 bytes,
280  * for all other protocols - 10 bytes (RFC 1490).
281  */
282 struct mbuf *sppp_fr_header (struct sppp *sp, struct mbuf *m,
283         int family)
284 {
285         STDDCL;
286         u_char *h;
287         int type, hlen;
288
289         /* Prepend the space for Frame Relay header. */
290         hlen = (family == AF_INET) ? 4 : 10;
291         M_PREPEND (m, hlen, M_NOWAIT);
292         if (! m)
293                 return 0;
294         h = mtod (m, u_char*);
295
296         /* Fill the header. */
297         h[0] = sp->fr_dlci >> 2 & 0xfc;
298         h[1] = sp->fr_dlci << 4 | 1;
299         h[2] = FR_UI;
300
301         switch (family) {
302         default:
303                 if (debug)
304                         printf (SPP_FMT "Cannot handle address family %d\n",
305                                 SPP_ARGS(ifp), family);
306                 m_freem (m);
307                 return 0;
308 #ifdef INET
309         case AF_INET:
310 #if 0 /* Crashes on fragmented packets */
311                 /*
312                  * Set the discard eligibility bit, if:
313                  * 1) no fragmentation
314                  * 2) length > 400 bytes
315                  * 3a) the protocol is UDP or
316                  * 3b) TCP data (no control bits)
317                  */
318                 {
319                 struct ip *ip = (struct ip*) (h + hlen);
320                 struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl);
321
322                 if (! (ip->ip_off & ~IP_DF) && ip->ip_len > 400 &&
323                     (ip->ip_p == IPPROTO_UDP ||
324                     ip->ip_p == IPPROTO_TCP && ! tcp->th_flags))
325                         h[1] |= FR_DE;
326                 }
327 #endif
328                 h[3] = FR_IP;
329                 return m;
330 #endif
331 #ifdef NS
332         case AF_NS:
333                 type = 0x8137;
334                 break;
335 #endif
336         }
337         h[3] = FR_PADDING;
338         h[4] = FR_SNAP;
339         h[5] = 0;
340         h[6] = 0;
341         h[7] = 0;
342         *(short*) (h+8) = htons(type);
343         return m;
344 }
345
346 /*
347  * Send periodical frame relay link verification messages via DLCI 0.
348  * Called every 10 seconds (default value of T391 timer is 10 sec).
349  * Every 6-th message is a full status request
350  * (default value of N391 counter is 6).
351  */
352 void sppp_fr_keepalive (struct sppp *sp)
353 {
354         STDDCL;
355         unsigned char *h, *p;
356         struct mbuf *m;
357
358         MGETHDR (m, M_NOWAIT, MT_DATA);
359         if (! m)
360                 return;
361         m->m_pkthdr.rcvif = 0;
362
363         h = mtod (m, u_char*);
364         p = h;
365         *p++ = 0;                       /* DLCI = 0 */
366         *p++ = 1;
367         *p++ = FR_UI;
368         *p++ = FR_SIGNALING;            /* NLPID = UNI call control */
369
370         *p++ = 0;                       /* call reference length = 0 */
371         *p++ = FR_MSG_ENQUIRY;          /* message type = status enquiry */
372
373         *p++ = FR_FLD_LSHIFT5;          /* locking shift 5 */
374
375         *p++ = FR_FLD_RTYPE;            /* report type field */
376         *p++ = 1;                       /* report type length = 1 */
377         if (sp->pp_seq[IDX_LCP] % 6)
378                 *p++ = FR_RTYPE_SHORT;  /* link verification only */
379         else
380                 *p++ = FR_RTYPE_FULL;   /* full status needed */
381
382         if (sp->pp_seq[IDX_LCP] >= 255)
383                 sp->pp_seq[IDX_LCP] = 0;
384         *p++ = FR_FLD_VERIFY;           /* link verification type field */
385         *p++ = 2;                       /* link verification field length = 2 */
386         *p++ = ++sp->pp_seq[IDX_LCP];   /* our sequence number */
387         *p++ = sp->pp_rseq[IDX_LCP];    /* last received sequence number */
388
389         m->m_pkthdr.len = m->m_len = p - h;
390         if (debug)
391                 printf (SPP_FMT "send lmi packet, seq=%d, rseq=%d\n",
392                         SPP_ARGS(ifp), (u_char) sp->pp_seq[IDX_LCP],
393                         (u_char) sp->pp_rseq[IDX_LCP]);
394
395         if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3))
396                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
397 }
398
399 /*
400  * Process the frame relay Inverse ARP request.
401  */
402 static void sppp_fr_arp (struct sppp *sp, struct arp_req *req,
403         u_short his_hardware_address)
404 {
405         STDDCL;
406         struct mbuf *m;
407         struct arp_req *reply;
408         u_char *h;
409         u_short my_hardware_address;
410         u_long his_ip_address, my_ip_address;
411
412         if ((ntohs (req->htype) != ARPHRD_FRELAY ||
413             ntohs (req->htype) != 16) || /* for BayNetworks routers */
414             ntohs (req->ptype) != ETHERTYPE_IP) {
415                 if (debug)
416                         printf (SPP_FMT "Invalid ARP hardware/protocol type = 0x%x/0x%x\n",
417                                 SPP_ARGS(ifp),
418                                 ntohs (req->htype), ntohs (req->ptype));
419                 return;
420         }
421         if (req->halen != 2 || req->palen != 4) {
422                 if (debug)
423                         printf (SPP_FMT "Invalid ARP hardware/protocol address length = %d/%d\n",
424                                 SPP_ARGS(ifp),
425                                 req->halen, req->palen);
426                 return;
427         }
428         switch (ntohs (req->op)) {
429         default:
430                 if (debug)
431                         printf (SPP_FMT "Invalid ARP op = 0x%x\n",
432                                 SPP_ARGS(ifp), ntohs (req->op));
433                 return;
434
435         case ARPOP_INVREPLY:
436                 /* Ignore. */
437                 return;
438
439         case ARPOP_INVREQUEST:
440                 my_hardware_address = ntohs (req->htarget);
441                 his_ip_address = ntohs (req->psource1) << 16 |
442                         ntohs (req->psource2);
443                 my_ip_address = ntohs (req->ptarget1) << 16 |
444                         ntohs (req->ptarget2);
445                 break;
446         }
447         if (debug)
448                 printf (SPP_FMT "got ARP request, source=0x%04x/%d.%d.%d.%d, target=0x%04x/%d.%d.%d.%d\n",
449                         SPP_ARGS(ifp), ntohs (req->hsource),
450                         (unsigned char) (his_ip_address >> 24),
451                         (unsigned char) (his_ip_address >> 16),
452                         (unsigned char) (his_ip_address >> 8),
453                         (unsigned char) his_ip_address,
454                         my_hardware_address,
455                         (unsigned char) (my_ip_address >> 24),
456                         (unsigned char) (my_ip_address >> 16),
457                         (unsigned char) (my_ip_address >> 8),
458                         (unsigned char) my_ip_address);
459
460         sppp_get_ip_addrs (sp, &my_ip_address, 0, 0);
461         if (! my_ip_address)
462                 return;         /* nothing to reply */
463
464         if (debug)
465                 printf (SPP_FMT "send ARP reply, source=0x%04x/%d.%d.%d.%d, target=0x%04x/%d.%d.%d.%d\n",
466                         SPP_ARGS(ifp), my_hardware_address,
467                         (unsigned char) (my_ip_address >> 24),
468                         (unsigned char) (my_ip_address >> 16),
469                         (unsigned char) (my_ip_address >> 8),
470                         (unsigned char) my_ip_address,
471                         his_hardware_address,
472                         (unsigned char) (his_ip_address >> 24),
473                         (unsigned char) (his_ip_address >> 16),
474                         (unsigned char) (his_ip_address >> 8),
475                         (unsigned char) his_ip_address);
476
477         /* Send the Inverse ARP reply. */
478         MGETHDR (m, M_NOWAIT, MT_DATA);
479         if (! m)
480                 return;
481         m->m_pkthdr.len = m->m_len = 10 + sizeof (*reply);
482         m->m_pkthdr.rcvif = 0;
483
484         h = mtod (m, u_char*);
485         reply = (struct arp_req*) (h + 10);
486
487         h[0] = his_hardware_address >> 8;
488         h[1] = his_hardware_address;
489         h[2] = FR_UI;
490         h[3] = FR_PADDING;
491         h[4] = FR_SNAP;
492         h[5] = 0;
493         h[6] = 0;
494         h[7] = 0;
495         *(short*) (h+8) = htons (ETHERTYPE_ARP);
496
497         reply->htype    = htons (ARPHRD_FRELAY);
498         reply->ptype    = htons (ETHERTYPE_IP);
499         reply->halen    = 2;
500         reply->palen    = 4;
501         reply->op       = htons (ARPOP_INVREPLY);
502         reply->hsource  = htons (my_hardware_address);
503         reply->psource1 = htonl (my_ip_address);
504         reply->psource2 = htonl (my_ip_address) >> 16;
505         reply->htarget  = htons (his_hardware_address);
506         reply->ptarget1 = htonl (his_ip_address);
507         reply->ptarget2 = htonl (his_ip_address) >> 16;
508
509         if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3))
510                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
511 }
512
513 /*
514  * Process the input signaling packet (DLCI 0).
515  * The implemented protocol is ANSI T1.617 Annex D.
516  */
517 static void sppp_fr_signal (struct sppp *sp, unsigned char *h, int len)
518 {
519         STDDCL;
520         u_char *p;
521         int dlci;
522
523         if (h[2] != FR_UI || h[3] != FR_SIGNALING || h[4] != 0) {
524                 if (debug)
525                         printf (SPP_FMT "Invalid signaling header\n",
526                                 SPP_ARGS(ifp));
527 bad:            if (debug) {
528                         printf ("%02x", *h++);
529                         while (--len > 0)
530                                 printf ("-%02x", *h++);
531                         printf ("\n");
532                 }
533                 return;
534         }
535         if (h[5] == FR_MSG_ENQUIRY) {
536                 if (len == FR_ENQUIRY_SIZE &&
537                     h[12] == (u_char) sp->pp_seq[IDX_LCP]) {
538                         sp->pp_seq[IDX_LCP] = random();
539                         printf (SPP_FMT "loopback detected\n",
540                                 SPP_ARGS(ifp));
541                 }
542                 return;
543         }
544         if (h[5] != FR_MSG_STATUS) {
545                 if (debug)
546                         printf (SPP_FMT "Unknown signaling message: 0x%02x\n",
547                                 SPP_ARGS(ifp), h[5]);
548                 goto bad;
549         }
550
551         /* Parse message fields. */
552         for (p=h+6; p<h+len; ) {
553                 switch (*p) {
554                 default:
555                         if (debug)
556                                 printf (SPP_FMT "Unknown signaling field 0x%x\n",
557                                         SPP_ARGS(ifp), *p);
558                         break;
559                 case FR_FLD_LSHIFT5:
560                 case FR_FLD_RTYPE:
561                         /* Ignore. */
562                         break;
563                 case FR_FLD_VERIFY:
564                         if (p[1] != 2) {
565                                 if (debug)
566                                         printf (SPP_FMT "Invalid signaling verify field length %d\n",
567                                                 SPP_ARGS(ifp), p[1]);
568                                 break;
569                         }
570                         sp->pp_rseq[IDX_LCP] = p[2];
571                         if (debug) {
572                                 printf (SPP_FMT "got lmi reply rseq=%d, seq=%d",
573                                         SPP_ARGS(ifp), p[2], p[3]);
574                                 if (p[3] != (u_char) sp->pp_seq[IDX_LCP])
575                                         printf (" (really %d)",
576                                                 (u_char) sp->pp_seq[IDX_LCP]);
577                                 printf ("\n");
578                         }
579                         break;
580                 case FR_FLD_PVC:
581                         if (p[1] < 3) {
582                                 if (debug)
583                                         printf (SPP_FMT "Invalid PVC status length %d\n",
584                                                 SPP_ARGS(ifp), p[1]);
585                                 break;
586                         }
587                         dlci = (p[2] << 4 & 0x3f0) | (p[3] >> 3 & 0x0f);
588                         if (! sp->fr_dlci)
589                                 sp->fr_dlci = dlci;
590                         if (sp->fr_status != p[4])
591                                 printf (SPP_FMT "DLCI %d %s%s\n",
592                                         SPP_ARGS(ifp), dlci,
593                                         p[4] & FR_DLCI_DELETE ? "deleted" :
594                                         p[4] & FR_DLCI_ACTIVE ? "active" : "passive",
595                                         p[4] & FR_DLCI_NEW ? ", new" : "");
596                         sp->fr_status = p[4];
597                         break;
598                 }
599                 if (*p & 0x80)
600                         ++p;
601                 else if (p < h+len+1 && p[1])
602                         p += 2 + p[1];
603                 else {
604                         if (debug)
605                                 printf (SPP_FMT "Invalid signaling field 0x%x\n",
606                                         SPP_ARGS(ifp), *p);
607                         goto bad;
608                 }
609         }
610 }