if_spppfr.c 15 KB

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