cleanup splnet's; if_imphost code interlocks at splimp now
[unix-history] / usr / src / sys / deprecated / netimp / if_imp.c
CommitLineData
ad100671 1/* if_imp.c 4.49 83/02/23 */
6c73ade6
BJ
2
3#include "imp.h"
4#if NIMP > 0
5/*
72e4f44e 6 * ARPANET IMP interface driver.
6c73ade6
BJ
7 *
8 * The IMP-host protocol is handled here, leaving
9 * hardware specifics to the lower level interface driver.
10 */
961945a8
SL
11#include "../machine/pte.h"
12
6c73ade6
BJ
13#include "../h/param.h"
14#include "../h/systm.h"
15#include "../h/mbuf.h"
6c73ade6
BJ
16#include "../h/buf.h"
17#include "../h/protosw.h"
18#include "../h/socket.h"
6c73ade6 19#include "../h/vmmac.h"
44afc493
SL
20#include "../h/time.h"
21#include "../h/kernel.h"
f4d55810 22#include "../h/errno.h"
6e7edb25
BJ
23
24#include "../vax/cpu.h"
25#include "../vax/mtpr.h"
39d536e6
BJ
26#include "../vaxuba/ubareg.h"
27#include "../vaxuba/ubavar.h"
6e7edb25 28
6c73ade6 29#include "../net/if.h"
6e7edb25 30#include "../net/route.h"
f4d55810 31
5e3649c6 32#include "../net/netisr.h"
6e7edb25
BJ
33#include "../netinet/in.h"
34#include "../netinet/in_systm.h"
35#include "../netinet/ip.h"
36#include "../netinet/ip_var.h"
b690198c 37/* define IMPLEADERS here to get leader printing code */
5e3649c6
BJ
38#include "../netimp/if_imp.h"
39#include "../netimp/if_imphost.h"
6c73ade6
BJ
40
41/*
42 * IMP software status per interface.
43 * (partially shared with the hardware specific module)
44 *
45 * Each interface is referenced by a network interface structure,
46 * imp_if, which the routing code uses to locate the interface.
47 * This structure contains the output queue for the interface, its
48 * address, ... IMP specific structures used in connecting the
49 * IMP software modules to the hardware specific interface routines
a2cd4df7
BJ
50 * are stored here. The common structures are made visible to the
51 * interface driver by passing a pointer to the hardware routine
52 * at "attach" time.
6c73ade6
BJ
53 *
54 * NOTE: imp_if and imp_cb are assumed adjacent in hardware code.
55 */
56struct imp_softc {
57 struct ifnet imp_if; /* network visible interface */
58 struct impcb imp_cb; /* hooks to hardware module */
59 u_char imp_state; /* current state of IMP */
60 char imp_dropcnt; /* used during initialization */
6c73ade6
BJ
61} imp_softc[NIMP];
62
63/*
64 * Messages from IMP regarding why
65 * it's going down.
66 */
e33b5b1a 67static char *impmessage[] = {
6c73ade6
BJ
68 "in 30 seconds",
69 "for hardware PM",
70 "to reload software",
71 "for emergency reset"
72};
73
a2cd4df7
BJ
74int impdown(), impinit(), impoutput();
75
6c73ade6
BJ
76/*
77 * IMP attach routine. Called from hardware device attach routine
78 * at configuration time with a pointer to the UNIBUS device structure.
79 * Sets up local state and returns pointer to base of ifnet+impcb
80 * structures. This is then used by the device's attach routine
81 * set up its back pointers.
82 */
30c36259 83impattach(ui, reset)
6c73ade6 84 struct uba_device *ui;
30c36259 85 int (*reset)();
6c73ade6
BJ
86{
87 struct imp_softc *sc = &imp_softc[ui->ui_unit];
88 register struct ifnet *ifp = &sc->imp_if;
ee787340 89 struct sockaddr_in *sin;
6c73ade6 90
6c73ade6
BJ
91 /* UNIT COULD BE AMBIGUOUS */
92 ifp->if_unit = ui->ui_unit;
93 ifp->if_name = "imp";
e431883e 94 ifp->if_mtu = IMPMTU - sizeof(struct imp_leader);
6c73ade6 95 ifp->if_net = ui->ui_flags;
ac697091 96 ifp->if_reset = reset;
aee8ddf8 97 /* the host and imp fields will be filled in by the imp */
ee787340
SL
98 sin = (struct sockaddr_in *)&ifp->if_addr;
99 sin->sin_family = AF_INET;
100 sin->sin_addr = if_makeaddr(ifp->if_net, 0);
a2cd4df7
BJ
101 ifp->if_init = impinit;
102 ifp->if_output = impoutput;
103 /* reset is handled at the hardware level */
6c73ade6 104 if_attach(ifp);
6c73ade6
BJ
105 return ((int)&sc->imp_if);
106}
107
108/*
109 * IMP initialization routine: call hardware module to
110 * setup UNIBUS resources, init state and get ready for
111 * NOOPs the IMP should send us, and that we want to drop.
112 */
113impinit(unit)
114 int unit;
115{
98b6195e 116 int s = splimp();
6c73ade6
BJ
117 register struct imp_softc *sc = &imp_softc[unit];
118
a2cd4df7
BJ
119 if ((*sc->imp_cb.ic_init)(unit) == 0) {
120 sc->imp_state = IMPS_DOWN;
ee787340 121 sc->imp_if.if_flags &= ~IFF_UP;
98b6195e 122 splx(s);
a2cd4df7
BJ
123 return;
124 }
6c73ade6 125 sc->imp_state = IMPS_INIT;
a2cd4df7 126 impnoops(sc);
98b6195e 127 splx(s);
6c73ade6
BJ
128}
129
130struct sockproto impproto = { PF_IMPLINK };
faad37c0
SL
131struct sockaddr_in impdst = { AF_IMPLINK };
132struct sockaddr_in impsrc = { AF_IMPLINK };
b690198c 133#ifdef IMPLEADERS
7dfb87a5 134int impprintfs = 0;
b690198c 135#endif
6c73ade6
BJ
136
137/*
138 * ARPAnet 1822 input routine.
139 * Called from hardware input interrupt routine to handle 1822
140 * IMP-host messages. Type 0 messages (non-control) are
141 * passed to higher level protocol processors on the basis
142 * of link number. Other type messages (control) are handled here.
143 */
a2cd4df7 144impinput(unit, m)
6c73ade6 145 int unit;
a2cd4df7 146 register struct mbuf *m;
6c73ade6 147{
6c73ade6
BJ
148 register struct imp_leader *ip;
149 register struct imp_softc *sc = &imp_softc[unit];
150 register struct host *hp;
151 register struct ifqueue *inq;
a2cd4df7 152 struct control_leader *cp;
6c73ade6 153 struct in_addr addr;
e33b5b1a 154 struct mbuf *next;
ee787340 155 struct sockaddr_in *sin;
6c73ade6 156
34c22ab5 157 /* verify leader length. */
a2cd4df7
BJ
158 if (m->m_len < sizeof(struct control_leader) &&
159 (m = m_pullup(m, sizeof(struct control_leader))) == 0)
160 return;
161 cp = mtod(m, struct control_leader *);
162 if (cp->dl_mtype == IMPTYPE_DATA)
163 if (m->m_len < sizeof(struct imp_leader) &&
164 (m = m_pullup(m, sizeof(struct imp_leader))) == 0)
165 return;
6c73ade6 166 ip = mtod(m, struct imp_leader *);
b690198c 167#ifdef IMPLEADERS
7dfb87a5
SL
168 if (impprintfs)
169 printleader("impinput", ip);
b690198c 170#endif
6c73ade6 171
34c22ab5 172 /* check leader type */
a2cd4df7
BJ
173 if (ip->il_format != IMP_NFF) {
174 sc->imp_if.if_collisions++; /* XXX */
6c73ade6 175 goto drop;
a2cd4df7 176 }
6c73ade6 177
ba45553a 178 if (ip->il_mtype != IMPTYPE_DATA) {
41e530c7 179#ifdef notdef
a2cd4df7 180 addr.s_net = ip->il_network;
41e530c7 181#else
ba45553a 182 addr.s_net = sc->imp_if.if_net;
41e530c7 183#endif
a2cd4df7
BJ
184 addr.s_imp = ip->il_imp;
185 addr.s_host = ip->il_host;
6c73ade6 186 }
6c73ade6
BJ
187 switch (ip->il_mtype) {
188
6c73ade6 189 case IMPTYPE_DATA:
6c73ade6
BJ
190 break;
191
192 /*
193 * IMP leader error. Reset the IMP and discard the packet.
194 */
195 case IMPTYPE_BADLEADER:
a0b7c7fb
SL
196 /*
197 * According to 1822 document, this message
198 * will be generated in response to the
199 * first noop sent to the IMP after
200 * the host resets the IMP interface.
201 */
a2cd4df7 202 if (sc->imp_state != IMPS_INIT) {
e33b5b1a 203 impmsg(sc, "leader error");
72e4f44e 204 hostreset(sc->imp_if.if_net);
a0b7c7fb
SL
205 impnoops(sc);
206 }
72e4f44e 207 goto drop;
6c73ade6
BJ
208
209 /*
210 * IMP going down. Print message, and if not immediate,
211 * set off a timer to insure things will be reset at the
212 * appropriate time.
213 */
214 case IMPTYPE_DOWN:
f32a85bb 215 if (sc->imp_state < IMPS_INIT)
47e51140 216 goto drop;
6c73ade6
BJ
217 if ((ip->il_link & IMP_DMASK) == 0) {
218 sc->imp_state = IMPS_GOINGDOWN;
668cc26d 219 timeout(impdown, (caddr_t)sc, 30 * hz);
6c73ade6 220 }
668cc26d
SL
221 impmsg(sc, "going down %s",
222 (u_int)impmessage[ip->il_link&IMP_DMASK]);
72e4f44e 223 goto drop;
6c73ade6
BJ
224
225 /*
226 * A NOP usually seen during the initialization sequence.
227 * Compare the local address with that in the message.
228 * Reset the local address notion if it doesn't match.
229 */
ee787340 230 case IMPTYPE_NOOP:
a0b7c7fb
SL
231 if (sc->imp_state == IMPS_DOWN) {
232 sc->imp_state = IMPS_INIT;
233 sc->imp_dropcnt = IMP_DROPCNT;
234 }
98b6195e 235 if (sc->imp_state == IMPS_INIT && --sc->imp_dropcnt > 0)
e431883e 236 goto drop;
98b6195e
SL
237 sin = (struct sockaddr_in *)&sc->imp_if.if_addr;
238 if (sin->sin_addr.s_host != ip->il_host ||
239 sin->sin_addr.s_imp != ip->il_imp) {
240 sc->imp_if.if_host[0] =
241 sin->sin_addr.s_host = ip->il_host;
242 sin->sin_addr.s_imp = ip->il_imp;
243 impmsg(sc, "reset (host %d/imp %d)", (u_int)ip->il_host,
244 ntohs(ip->il_imp));
245 }
a2cd4df7 246 sc->imp_state = IMPS_UP;
ee787340 247 sc->imp_if.if_flags |= IFF_UP;
88f80700 248 if_rtinit(&sc->imp_if, RTF_UP);
e431883e 249 goto drop;
6c73ade6
BJ
250
251 /*
72e4f44e
SL
252 * RFNM or INCOMPLETE message, send next
253 * message on the q. We could pass incomplete's
254 * up to the next level, but this currently isn't
255 * needed.
6c73ade6
BJ
256 */
257 case IMPTYPE_RFNM:
258 case IMPTYPE_INCOMPLETE:
ba45553a
SL
259 if (hp = hostlookup(addr)) {
260 if (hp->h_rfnm == 0)
261 hp->h_flags &= ~HF_INUSE;
262 else if (next = hostdeque(hp))
263 (void) impsnd(&sc->imp_if, next);
264 }
e431883e 265 goto drop;
6c73ade6
BJ
266
267 /*
268 * Host or IMP can't be reached. Flush any packets
269 * awaiting transmission and release the host structure.
6c73ade6
BJ
270 */
271 case IMPTYPE_HOSTDEAD:
ad100671 272 case IMPTYPE_HOSTUNREACH:
6e7edb25
BJ
273 impnotify((int)ip->il_mtype, (struct control_leader *)ip,
274 hostlookup(addr));
41e530c7 275 goto rawlinkin;
6c73ade6
BJ
276
277 /*
278 * Error in data. Clear RFNM status for this host and send
279 * noops to the IMP to clear the interface.
280 */
ad100671 281 case IMPTYPE_BADDATA:
e33b5b1a 282 impmsg(sc, "data error");
ba45553a 283 if (hp = hostlookup(addr))
6c73ade6
BJ
284 hp->h_rfnm = 0;
285 impnoops(sc);
72e4f44e 286 goto drop;
6c73ade6
BJ
287
288 /*
a0b7c7fb 289 * Interface reset.
6c73ade6
BJ
290 */
291 case IMPTYPE_RESET:
e33b5b1a 292 impmsg(sc, "interface reset");
a0b7c7fb 293 impnoops(sc);
72e4f44e 294 goto drop;
6c73ade6
BJ
295
296 default:
297 sc->imp_if.if_collisions++; /* XXX */
72e4f44e 298 goto drop;
6c73ade6
BJ
299 }
300
301 /*
34c22ab5
BJ
302 * Data for a protocol. Dispatch to the appropriate
303 * protocol routine (running at software interrupt).
304 * If this isn't a raw interface, advance pointer
305 * into mbuf past leader.
6c73ade6
BJ
306 */
307 switch (ip->il_link) {
308
309#ifdef INET
310 case IMPLINK_IP:
311 m->m_len -= sizeof(struct imp_leader);
312 m->m_off += sizeof(struct imp_leader);
9c8692e9 313 schednetisr(NETISR_IP);
6c73ade6
BJ
314 inq = &ipintrq;
315 break;
316#endif
317
318 default:
654fef96 319 rawlinkin:
6c73ade6 320 impproto.sp_protocol = ip->il_link;
ee787340
SL
321 sin = (struct sockaddr_in *)&sc->imp_if.if_addr;
322 impdst.sin_addr = sin->sin_addr;;
faad37c0
SL
323 impsrc.sin_addr.s_net = ip->il_network;
324 impsrc.sin_addr.s_host = ip->il_host;
325 impsrc.sin_addr.s_imp = ip->il_imp;
57aa3090
SL
326 raw_input(m, &impproto, (struct sockaddr *)&impsrc,
327 (struct sockaddr *)&impdst);
6c73ade6
BJ
328 return;
329 }
1e977657
BJ
330 if (IF_QFULL(inq)) {
331 IF_DROP(inq);
332 goto drop;
333 }
6c73ade6
BJ
334 IF_ENQUEUE(inq, m);
335 return;
336
337drop:
338 m_freem(m);
339}
340
a0b7c7fb
SL
341/*
342 * Bring the IMP down after notification.
343 */
344impdown(sc)
345 struct imp_softc *sc;
346{
ad100671 347 int s = splimp();
1e977657 348
a0b7c7fb 349 sc->imp_state = IMPS_DOWN;
e33b5b1a 350 impmsg(sc, "marked down");
ba45553a 351 hostreset(sc->imp_if.if_net);
72e4f44e 352 if_down(&sc->imp_if);
ad100671 353 splx(s);
a0b7c7fb
SL
354}
355
6c73ade6 356/*VARARGS*/
e33b5b1a 357impmsg(sc, fmt, a1, a2)
6c73ade6
BJ
358 struct imp_softc *sc;
359 char *fmt;
668cc26d 360 u_int a1;
6c73ade6 361{
1e977657 362
6c73ade6
BJ
363 printf("imp%d: ", sc->imp_if.if_unit);
364 printf(fmt, a1, a2);
365 printf("\n");
366}
367
72e4f44e
SL
368/*
369 * Process an IMP "error" message, passing this
370 * up to the higher level protocol.
371 */
372impnotify(what, cp, hp)
373 int what;
374 struct control_leader *cp;
375 struct host *hp;
376{
377 struct in_addr in;
378
379#ifdef notdef
380 in.s_net = cp->dl_network;
381#else
ba45553a 382 in.s_net = 10; /* XXX */
72e4f44e
SL
383#endif
384 in.s_host = cp->dl_host;
385 in.s_imp = cp->dl_imp;
386 if (cp->dl_link != IMPLINK_IP)
387 raw_ctlinput(what, (caddr_t)&in);
388 else
389 ip_ctlinput(what, (caddr_t)&in);
ba45553a
SL
390 if (hp) {
391 hp->h_flags |= (1 << what);
72e4f44e 392 hostfree(hp);
ba45553a 393 }
72e4f44e
SL
394}
395
6c73ade6
BJ
396/*
397 * ARPAnet 1822 output routine.
398 * Called from higher level protocol routines to set up messages for
399 * transmission to the imp. Sets up the header and calls impsnd to
400 * enqueue the message for this IMP's hardware driver.
401 */
ee787340 402impoutput(ifp, m0, dst)
6c73ade6
BJ
403 register struct ifnet *ifp;
404 struct mbuf *m0;
ee787340 405 struct sockaddr *dst;
6c73ade6
BJ
406{
407 register struct imp_leader *imp;
408 register struct mbuf *m = m0;
39d536e6 409 int dhost, dimp, dlink, len, dnet;
8a2f82db 410 int error = 0;
6c73ade6
BJ
411
412 /*
413 * Don't even try if the IMP is unavailable.
414 */
8a2f82db
SL
415 if (imp_softc[ifp->if_unit].imp_state != IMPS_UP) {
416 error = ENETDOWN;
a0b7c7fb 417 goto drop;
8a2f82db 418 }
6c73ade6 419
ee787340 420 switch (dst->sa_family) {
6c73ade6
BJ
421
422#ifdef INET
ee787340
SL
423 case AF_INET: {
424 struct ip *ip = mtod(m0, struct ip *);
425 struct sockaddr_in *sin = (struct sockaddr_in *)dst;
6c73ade6 426
ee787340
SL
427 dhost = sin->sin_addr.s_host;
428 dimp = sin->sin_addr.s_impno;
6c73ade6 429 dlink = IMPLINK_IP;
1e63a6ab 430 dnet = 0;
668cc26d 431 len = ntohs((u_short)ip->ip_len);
6c73ade6
BJ
432 break;
433 }
434#endif
ee787340 435 case AF_IMPLINK:
6c73ade6
BJ
436 goto leaderexists;
437
438 default:
ee787340
SL
439 printf("imp%d: can't handle af%d\n", ifp->if_unit,
440 dst->sa_family);
8a2f82db 441 error = EAFNOSUPPORT;
a0b7c7fb 442 goto drop;
6c73ade6
BJ
443 }
444
445 /*
446 * Add IMP leader. If there's not enough space in the
447 * first mbuf, allocate another. If that should fail, we
448 * drop this sucker.
449 */
450 if (m->m_off > MMAXOFF ||
451 MMINOFF + sizeof(struct imp_leader) > m->m_off) {
cce93e4b 452 m = m_get(M_DONTWAIT, MT_HEADER);
8a2f82db
SL
453 if (m == 0) {
454 error = ENOBUFS;
a0b7c7fb 455 goto drop;
8a2f82db 456 }
6c73ade6 457 m->m_next = m0;
6c73ade6
BJ
458 m->m_len = sizeof(struct imp_leader);
459 } else {
460 m->m_off -= sizeof(struct imp_leader);
461 m->m_len += sizeof(struct imp_leader);
462 }
463 imp = mtod(m, struct imp_leader *);
464 imp->il_format = IMP_NFF;
41e530c7 465 imp->il_mtype = IMPTYPE_DATA;
1e63a6ab 466 imp->il_network = dnet;
6c73ade6 467 imp->il_host = dhost;
1e63a6ab 468 imp->il_imp = htons((u_short)dimp);
668cc26d
SL
469 imp->il_length =
470 htons((u_short)(len + sizeof(struct imp_leader)) << 3);
6c73ade6 471 imp->il_link = dlink;
41e530c7 472 imp->il_flags = imp->il_htype = imp->il_subtype = 0;
6c73ade6
BJ
473
474leaderexists:
6c73ade6 475 return (impsnd(ifp, m));
a0b7c7fb
SL
476drop:
477 m_freem(m0);
8a2f82db 478 return (error);
6c73ade6
BJ
479}
480
481/*
482 * Put a message on an interface's output queue.
483 * Perform RFNM counting: no more than 8 message may be
484 * in flight to any one host.
485 */
486impsnd(ifp, m)
487 struct ifnet *ifp;
488 struct mbuf *m;
489{
490 register struct imp_leader *ip;
491 register struct host *hp;
492 struct impcb *icp;
ba45553a 493 int s, error;
6c73ade6
BJ
494
495 ip = mtod(m, struct imp_leader *);
496
497 /*
498 * Do RFNM counting for data messages
499 * (no more than 8 outstanding to any host)
500 */
ba45553a 501 s = splimp();
6c73ade6
BJ
502 if (ip->il_mtype == IMPTYPE_DATA) {
503 struct in_addr addr;
504
41e530c7 505#ifdef notdef
a2cd4df7 506 addr.s_net = ip->il_network;
41e530c7 507#else
ba45553a 508 addr.s_net = ifp->if_net; /* XXX */
41e530c7 509#endif
6c73ade6
BJ
510 addr.s_host = ip->il_host;
511 addr.s_imp = ip->il_imp;
a2cd4df7
BJ
512 if ((hp = hostlookup(addr)) == 0)
513 hp = hostenter(addr);
ba45553a 514 if (hp && (hp->h_flags & (HF_DEAD|HF_UNREACH))) {
67387c9c 515 error = hp->h_flags&HF_DEAD ? EHOSTDOWN : EHOSTUNREACH;
ba45553a
SL
516 hp->h_timer = HOSTTIMER;
517 hp->h_flags &= ~HF_INUSE;
518 goto bad;
ba45553a 519 }
6c73ade6
BJ
520
521 /*
a0b7c7fb 522 * If IMP would block, queue until RFNM
6c73ade6
BJ
523 */
524 if (hp) {
6c73ade6
BJ
525 if (hp->h_rfnm < 8) {
526 hp->h_rfnm++;
527 goto enque;
528 }
fcd78660
BJ
529 if (hp->h_qcnt < 8) { /* high water mark */
530 HOST_ENQUE(hp, m);
531 goto start;
532 }
6c73ade6 533 }
ba45553a
SL
534 error = ENOBUFS;
535 goto bad;
6c73ade6
BJ
536 }
537enque:
1e977657
BJ
538 if (IF_QFULL(&ifp->if_snd)) {
539 IF_DROP(&ifp->if_snd);
ba45553a
SL
540 error = ENOBUFS;
541bad:
1e977657 542 m_freem(m);
ba45553a
SL
543 splx(s);
544 return (error);
1e977657 545 }
6c73ade6 546 IF_ENQUEUE(&ifp->if_snd, m);
6c73ade6
BJ
547start:
548 icp = &imp_softc[ifp->if_unit].imp_cb;
549 if (icp->ic_oactive == 0)
550 (*icp->ic_start)(ifp->if_unit);
70e3101c 551 splx(s);
8a2f82db 552 return (0);
6c73ade6
BJ
553}
554
555/*
556 * Put three 1822 NOOPs at the head of the output queue.
557 * Part of host-IMP initialization procedure.
558 * (Should return success/failure, but noone knows
559 * what to do with this, so why bother?)
0dc78444
SL
560 * This routine is always called at splimp, so we don't
561 * protect the call to IF_PREPEND.
6c73ade6
BJ
562 */
563impnoops(sc)
564 register struct imp_softc *sc;
565{
566 register i;
567 register struct mbuf *m;
a2cd4df7 568 register struct control_leader *cp;
6c73ade6 569
6c73ade6 570 sc->imp_dropcnt = IMP_DROPCNT;
a2cd4df7 571 for (i = 0; i < IMP_DROPCNT + 1; i++ ) {
cce93e4b 572 if ((m = m_getclr(M_DONTWAIT, MT_HEADER)) == 0)
6c73ade6 573 return;
a2cd4df7
BJ
574 m->m_len = sizeof(struct control_leader);
575 cp = mtod(m, struct control_leader *);
576 cp->dl_format = IMP_NFF;
577 cp->dl_link = i;
578 cp->dl_mtype = IMPTYPE_NOOP;
6c73ade6 579 IF_PREPEND(&sc->imp_if.if_snd, m);
6c73ade6
BJ
580 }
581 if (sc->imp_cb.ic_oactive == 0)
582 (*sc->imp_cb.ic_start)(sc->imp_if.if_unit);
583}
7dfb87a5
SL
584
585#ifdef IMPLEADERS
586printleader(routine, ip)
587 char *routine;
588 register struct imp_leader *ip;
589{
590 printf("%s: ", routine);
591 printbyte((char *)ip, 12);
592 printf("<fmt=%x,net=%x,flags=%x,mtype=", ip->il_format, ip->il_network,
593 ip->il_flags);
594 if (ip->il_mtype <= IMPTYPE_READY)
595 printf("%s,", impleaders[ip->il_mtype]);
596 else
597 printf("%x,", ip->il_mtype);
598 printf("htype=%x,host=%x,imp=%x,link=", ip->il_htype, ip->il_host,
599 ntohs(ip->il_imp));
600 if (ip->il_link == IMPLINK_IP)
601 printf("ip,");
602 else
603 printf("%x,", ip->il_link);
604 printf("subtype=%x,len=%x>\n",ip->il_subtype,ntohs(ip->il_length)>>3);
605}
606
607printbyte(cp, n)
608 register char *cp;
609 int n;
610{
611 register i, j, c;
612
613 for (i=0; i<n; i++) {
614 c = *cp++;
615 for (j=0; j<2; j++)
616 putchar("0123456789abcdef"[(c>>((1-j)*4))&0xf]);
617 putchar(' ');
618 }
619 putchar('\n');
620}
621#endif
41e530c7 622#endif