Home | History | Annotate | Line # | Download | only in dist
      1   1.1  christos /*
      2   1.1  christos  * Copyright (c) 1993, 1994, 1995, 1996
      3   1.1  christos  *	The Regents of the University of California.  All rights reserved.
      4   1.1  christos  *
      5   1.1  christos  * Redistribution and use in source and binary forms, with or without
      6   1.1  christos  * modification, are permitted provided that: (1) source code distributions
      7   1.1  christos  * retain the above copyright notice and this paragraph in its entirety, (2)
      8   1.1  christos  * distributions including binary code include the above copyright notice and
      9   1.1  christos  * this paragraph in its entirety in the documentation or other materials
     10   1.1  christos  * provided with the distribution, and (3) all advertising materials mentioning
     11   1.1  christos  * features or use of this software display the following acknowledgement:
     12   1.1  christos  * ``This product includes software developed by the University of California,
     13   1.1  christos  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
     14   1.1  christos  * the University nor the names of its contributors may be used to endorse
     15   1.1  christos  * or promote products derived from this software without specific prior
     16   1.1  christos  * written permission.
     17   1.1  christos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
     18   1.1  christos  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
     19   1.1  christos  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     20   1.1  christos  */
     21   1.1  christos 
     22   1.2  christos #include <sys/cdefs.h>
     23   1.1  christos #ifndef lint
     24  1.12  christos __RCSID("$NetBSD: print-wb.c,v 1.12 2024/09/02 16:15:33 christos Exp $");
     25   1.1  christos #endif
     26   1.1  christos 
     27   1.7       spz /* \summary: White Board printer */
     28   1.7       spz 
     29  1.11  christos #include <config.h>
     30   1.1  christos 
     31  1.11  christos #include "netdissect-stdinc.h"
     32   1.1  christos 
     33  1.11  christos #define ND_LONGJMP_FROM_TCHECK
     34   1.6  christos #include "netdissect.h"
     35   1.1  christos #include "addrtoname.h"
     36   1.1  christos #include "extract.h"
     37   1.1  christos 
     38   1.1  christos 
     39  1.11  christos #if 0
     40   1.1  christos /*
     41   1.1  christos  * Largest packet size.  Everything should fit within this space.
     42   1.1  christos  * For instance, multiline objects are sent piecewise.
     43   1.1  christos  */
     44   1.1  christos #define MAXFRAMESIZE 1024
     45  1.11  christos #endif
     46   1.1  christos 
     47   1.1  christos /*
     48   1.1  christos  * Multiple drawing ops can be sent in one packet.  Each one starts on a
     49   1.1  christos  * an even multiple of DOP_ALIGN bytes, which must be a power of two.
     50   1.1  christos  */
     51   1.1  christos #define DOP_ALIGN 4
     52  1.11  christos #define DOP_ROUNDUP(x)	roundup2(x, DOP_ALIGN)
     53   1.1  christos #define DOP_NEXT(d)\
     54   1.6  christos 	((const struct dophdr *)((const u_char *)(d) + \
     55  1.11  christos 				DOP_ROUNDUP(GET_BE_U_2((d)->dh_len) + sizeof(*(d)))))
     56   1.1  christos 
     57   1.1  christos /*
     58   1.1  christos  * Format of the whiteboard packet header.
     59   1.1  christos  * The transport level header.
     60   1.1  christos  */
     61   1.1  christos struct pkt_hdr {
     62  1.11  christos 	nd_uint32_t ph_src;	/* site id of source */
     63  1.11  christos 	nd_uint32_t ph_ts;	/* time stamp (for skew computation) */
     64  1.11  christos 	nd_uint16_t ph_version;	/* version number */
     65  1.11  christos 	nd_uint8_t ph_type;	/* message type */
     66  1.11  christos 	nd_uint8_t ph_flags;	/* message flags */
     67   1.1  christos };
     68   1.1  christos 
     69   1.1  christos /* Packet types */
     70   1.1  christos #define PT_DRAWOP	0	/* drawing operation */
     71   1.1  christos #define PT_ID		1	/* announcement packet */
     72   1.1  christos #define PT_RREQ		2	/* repair request */
     73   1.1  christos #define PT_RREP		3	/* repair reply */
     74   1.1  christos #define PT_KILL		4	/* terminate participation */
     75   1.1  christos #define PT_PREQ         5       /* page vector request */
     76   1.1  christos #define PT_PREP         7       /* page vector reply */
     77   1.1  christos 
     78  1.11  christos #if 0
     79   1.1  christos #ifdef PF_USER
     80   1.1  christos #undef PF_USER			/* {Digital,Tru64} UNIX define this, alas */
     81   1.1  christos #endif
     82   1.1  christos 
     83   1.1  christos /* flags */
     84   1.1  christos #define PF_USER		0x01	/* hint that packet has interactive data */
     85   1.1  christos #define PF_VIS		0x02	/* only visible ops wanted */
     86  1.11  christos #endif
     87   1.1  christos 
     88   1.1  christos struct PageID {
     89  1.11  christos 	nd_uint32_t p_sid;		/* session id of initiator */
     90  1.11  christos 	nd_uint32_t p_uid;		/* page number */
     91   1.1  christos };
     92   1.1  christos 
     93   1.1  christos struct dophdr {
     94  1.11  christos 	nd_uint32_t	dh_ts;		/* sender's timestamp */
     95  1.11  christos 	nd_uint16_t	dh_len;		/* body length */
     96  1.11  christos 	nd_uint8_t	dh_flags;
     97  1.11  christos 	nd_uint8_t	dh_type;	/* body type */
     98   1.1  christos 	/* body follows */
     99   1.1  christos };
    100   1.1  christos /*
    101   1.1  christos  * Drawing op sub-types.
    102   1.1  christos  */
    103   1.1  christos #define DT_RECT         2
    104   1.1  christos #define DT_LINE         3
    105   1.1  christos #define DT_ML           4
    106   1.1  christos #define DT_DEL          5
    107   1.1  christos #define DT_XFORM        6
    108   1.1  christos #define DT_ELL          7
    109   1.1  christos #define DT_CHAR         8
    110   1.1  christos #define DT_STR          9
    111   1.1  christos #define DT_NOP          10
    112   1.1  christos #define DT_PSCODE       11
    113   1.1  christos #define DT_PSCOMP       12
    114   1.1  christos #define DT_REF          13
    115   1.1  christos #define DT_SKIP         14
    116   1.1  christos #define DT_HOLE         15
    117  1.11  christos static const struct tok dop_str[] = {
    118  1.11  christos 	{ DT_RECT,   "RECT"   },
    119  1.11  christos 	{ DT_LINE,   "LINE"   },
    120  1.11  christos 	{ DT_ML,     "ML"     },
    121  1.11  christos 	{ DT_DEL,    "DEL"    },
    122  1.11  christos 	{ DT_XFORM,  "XFORM"  },
    123  1.11  christos 	{ DT_ELL,    "ELL"    },
    124  1.11  christos 	{ DT_CHAR,   "CHAR"   },
    125  1.11  christos 	{ DT_STR,    "STR"    },
    126  1.11  christos 	{ DT_NOP,    "NOP"    },
    127  1.11  christos 	{ DT_PSCODE, "PSCODE" },
    128  1.11  christos 	{ DT_PSCOMP, "PSCOMP" },
    129  1.11  christos 	{ DT_REF,    "REF"    },
    130  1.11  christos 	{ DT_SKIP,   "SKIP"   },
    131  1.11  christos 	{ DT_HOLE,   "HOLE"   },
    132  1.11  christos 	{ 0, NULL }
    133  1.11  christos };
    134   1.1  christos 
    135   1.1  christos /*
    136   1.1  christos  * A drawing operation.
    137   1.1  christos  */
    138   1.1  christos struct pkt_dop {
    139   1.1  christos 	struct PageID pd_page;	/* page that operations apply to */
    140  1.11  christos 	nd_uint32_t	pd_sseq;	/* start sequence number */
    141  1.11  christos 	nd_uint32_t	pd_eseq;	/* end sequence number */
    142   1.1  christos 	/* drawing ops follow */
    143   1.1  christos };
    144   1.1  christos 
    145   1.1  christos /*
    146   1.1  christos  * A repair request.
    147   1.1  christos  */
    148   1.1  christos struct pkt_rreq {
    149  1.11  christos         nd_uint32_t pr_id;        /* source id of drawops to be repaired */
    150  1.11  christos         struct PageID pr_page;    /* page of drawops */
    151  1.11  christos         nd_uint32_t pr_sseq;      /* start seqno */
    152  1.11  christos         nd_uint32_t pr_eseq;      /* end seqno */
    153   1.1  christos };
    154   1.1  christos 
    155   1.1  christos /*
    156   1.1  christos  * A repair reply.
    157   1.1  christos  */
    158   1.1  christos struct pkt_rrep {
    159  1.11  christos 	nd_uint32_t pr_id;	/* original site id of ops  */
    160   1.1  christos 	struct pkt_dop pr_dop;
    161   1.1  christos 	/* drawing ops follow */
    162   1.1  christos };
    163   1.1  christos 
    164   1.1  christos struct id_off {
    165  1.11  christos         nd_uint32_t id;
    166  1.11  christos         nd_uint32_t off;
    167   1.1  christos };
    168   1.1  christos 
    169   1.1  christos struct pgstate {
    170  1.11  christos 	nd_uint32_t slot;
    171   1.1  christos 	struct PageID page;
    172  1.11  christos 	nd_uint16_t nid;
    173  1.11  christos 	nd_uint16_t rsvd;
    174   1.1  christos         /* seqptr's */
    175   1.1  christos };
    176   1.1  christos 
    177   1.1  christos /*
    178   1.1  christos  * An announcement packet.
    179   1.1  christos  */
    180   1.1  christos struct pkt_id {
    181  1.11  christos 	nd_uint32_t pi_mslot;
    182   1.1  christos         struct PageID    pi_mpage;        /* current page */
    183   1.1  christos 	struct pgstate pi_ps;
    184   1.1  christos         /* seqptr's */
    185   1.1  christos         /* null-terminated site name */
    186   1.1  christos };
    187   1.1  christos 
    188   1.1  christos struct pkt_preq {
    189   1.1  christos         struct PageID  pp_page;
    190  1.11  christos         nd_uint32_t  pp_low;
    191  1.11  christos         nd_uint32_t  pp_high;
    192   1.1  christos };
    193   1.1  christos 
    194   1.1  christos struct pkt_prep {
    195  1.11  christos         nd_uint32_t  pp_n;           /* size of pageid array */
    196   1.1  christos         /* pgstate's follow */
    197   1.1  christos };
    198   1.1  christos 
    199   1.1  christos static int
    200   1.4  christos wb_id(netdissect_options *ndo,
    201   1.4  christos       const struct pkt_id *id, u_int len)
    202   1.1  christos {
    203  1.11  christos 	u_int i;
    204  1.11  christos 	const u_char *sitename;
    205   1.1  christos 	const struct id_off *io;
    206   1.1  christos 	char c;
    207  1.11  christos 	u_int nid;
    208   1.1  christos 
    209  1.11  christos 	ND_PRINT(" wb-id:");
    210  1.11  christos 	if (len < sizeof(*id))
    211   1.1  christos 		return (-1);
    212   1.1  christos 	len -= sizeof(*id);
    213   1.1  christos 
    214  1.11  christos 	ND_PRINT(" %u/%s:%u (max %u/%s:%u) ",
    215  1.11  christos 	       GET_BE_U_4(id->pi_ps.slot),
    216  1.11  christos 	       GET_IPADDR_STRING(id->pi_ps.page.p_sid),
    217  1.11  christos 	       GET_BE_U_4(id->pi_ps.page.p_uid),
    218  1.11  christos 	       GET_BE_U_4(id->pi_mslot),
    219  1.11  christos 	       GET_IPADDR_STRING(id->pi_mpage.p_sid),
    220  1.11  christos 	       GET_BE_U_4(id->pi_mpage.p_uid));
    221  1.11  christos 	/* now the rest of the fixed-size part of struct pkt_id */
    222  1.11  christos 	ND_TCHECK_SIZE(id);
    223   1.1  christos 
    224  1.11  christos 	nid = GET_BE_U_2(id->pi_ps.nid);
    225  1.11  christos 	if (len < sizeof(*io) * nid)
    226  1.11  christos 		return (-1);
    227   1.1  christos 	len -= sizeof(*io) * nid;
    228   1.6  christos 	io = (const struct id_off *)(id + 1);
    229  1.11  christos 	sitename = (const u_char *)(io + nid);
    230   1.1  christos 
    231   1.1  christos 	c = '<';
    232  1.11  christos 	for (i = 0; i < nid; ++io, ++i) {
    233  1.11  christos 		ND_PRINT("%c%s:%u",
    234  1.11  christos 		    c, GET_IPADDR_STRING(io->id), GET_BE_U_4(io->off));
    235   1.1  christos 		c = ',';
    236   1.1  christos 	}
    237  1.11  christos 	ND_PRINT("> \"");
    238  1.11  christos 	nd_printjnp(ndo, sitename, len);
    239  1.11  christos 	ND_PRINT("\"");
    240  1.11  christos 	return (0);
    241   1.1  christos }
    242   1.1  christos 
    243   1.1  christos static int
    244   1.4  christos wb_rreq(netdissect_options *ndo,
    245   1.4  christos         const struct pkt_rreq *rreq, u_int len)
    246   1.1  christos {
    247  1.11  christos 	ND_PRINT(" wb-rreq:");
    248  1.11  christos 	if (len < sizeof(*rreq))
    249   1.1  christos 		return (-1);
    250   1.1  christos 
    251  1.11  christos 	ND_PRINT(" please repair %s %s:%u<%u:%u>",
    252  1.11  christos 	       GET_IPADDR_STRING(rreq->pr_id),
    253  1.11  christos 	       GET_IPADDR_STRING(rreq->pr_page.p_sid),
    254  1.11  christos 	       GET_BE_U_4(rreq->pr_page.p_uid),
    255  1.11  christos 	       GET_BE_U_4(rreq->pr_sseq),
    256  1.11  christos 	       GET_BE_U_4(rreq->pr_eseq));
    257   1.1  christos 	return (0);
    258   1.1  christos }
    259   1.1  christos 
    260   1.1  christos static int
    261   1.4  christos wb_preq(netdissect_options *ndo,
    262   1.4  christos         const struct pkt_preq *preq, u_int len)
    263   1.1  christos {
    264  1.11  christos 	ND_PRINT(" wb-preq:");
    265  1.11  christos 	if (len < sizeof(*preq))
    266   1.1  christos 		return (-1);
    267   1.1  christos 
    268  1.11  christos 	ND_PRINT(" need %u/%s:%u",
    269  1.11  christos 	       GET_BE_U_4(preq->pp_low),
    270  1.11  christos 	       GET_IPADDR_STRING(preq->pp_page.p_sid),
    271  1.11  christos 	       GET_BE_U_4(preq->pp_page.p_uid));
    272  1.11  christos 	/* now the rest of the fixed-size part of struct pkt_req */
    273  1.11  christos 	ND_TCHECK_SIZE(preq);
    274   1.1  christos 	return (0);
    275   1.1  christos }
    276   1.1  christos 
    277   1.1  christos static int
    278   1.4  christos wb_prep(netdissect_options *ndo,
    279   1.4  christos         const struct pkt_prep *prep, u_int len)
    280   1.1  christos {
    281  1.11  christos 	u_int n;
    282   1.1  christos 	const struct pgstate *ps;
    283   1.1  christos 
    284  1.11  christos 	ND_PRINT(" wb-prep:");
    285  1.11  christos 	if (len < sizeof(*prep))
    286   1.1  christos 		return (-1);
    287  1.11  christos 	n = GET_BE_U_4(prep->pp_n);
    288   1.1  christos 	ps = (const struct pgstate *)(prep + 1);
    289  1.11  christos 	while (n != 0) {
    290   1.1  christos 		const struct id_off *io, *ie;
    291   1.1  christos 		char c = '<';
    292   1.1  christos 
    293  1.11  christos 		ND_PRINT(" %u/%s:%u",
    294  1.11  christos 		    GET_BE_U_4(ps->slot),
    295  1.11  christos 		    GET_IPADDR_STRING(ps->page.p_sid),
    296  1.11  christos 		    GET_BE_U_4(ps->page.p_uid));
    297  1.11  christos 		/* now the rest of the fixed-size part of struct pgstate */
    298  1.11  christos 		ND_TCHECK_SIZE(ps);
    299   1.6  christos 		io = (const struct id_off *)(ps + 1);
    300  1.11  christos 		for (ie = io + GET_U_1(ps->nid); io < ie; ++io) {
    301  1.11  christos 			ND_PRINT("%c%s:%u", c, GET_IPADDR_STRING(io->id),
    302  1.11  christos 			    GET_BE_U_4(io->off));
    303   1.1  christos 			c = ',';
    304   1.1  christos 		}
    305  1.11  christos 		ND_PRINT(">");
    306   1.6  christos 		ps = (const struct pgstate *)io;
    307  1.11  christos 		n--;
    308   1.1  christos 	}
    309  1.11  christos 	return 0;
    310   1.1  christos }
    311   1.1  christos 
    312  1.11  christos static void
    313   1.5  christos wb_dops(netdissect_options *ndo, const struct pkt_dop *dop,
    314   1.5  christos         uint32_t ss, uint32_t es)
    315   1.1  christos {
    316   1.5  christos 	const struct dophdr *dh = (const struct dophdr *)((const u_char *)dop + sizeof(*dop));
    317   1.5  christos 
    318  1.11  christos 	ND_PRINT(" <");
    319   1.1  christos 	for ( ; ss <= es; ++ss) {
    320  1.11  christos 		u_int t;
    321   1.5  christos 
    322  1.11  christos 		t = GET_U_1(dh->dh_type);
    323   1.1  christos 
    324  1.11  christos 		ND_PRINT(" %s", tok2str(dop_str, "dop-%u!", t));
    325  1.11  christos 		if (t == DT_SKIP || t == DT_HOLE) {
    326  1.11  christos 			uint32_t ts = GET_BE_U_4(dh->dh_ts);
    327  1.11  christos 			ND_PRINT("%u", ts - ss + 1);
    328  1.11  christos 			if (ss > ts || ts > es) {
    329  1.11  christos 				ND_PRINT("[|]");
    330  1.11  christos 				if (ts < ss)
    331  1.11  christos 					return;
    332   1.1  christos 			}
    333  1.11  christos 			ss = ts;
    334   1.1  christos 		}
    335   1.1  christos 		dh = DOP_NEXT(dh);
    336   1.1  christos 	}
    337  1.11  christos 	ND_PRINT(" >");
    338   1.1  christos }
    339   1.1  christos 
    340   1.1  christos static int
    341   1.4  christos wb_rrep(netdissect_options *ndo,
    342   1.4  christos         const struct pkt_rrep *rrep, u_int len)
    343   1.1  christos {
    344   1.1  christos 	const struct pkt_dop *dop = &rrep->pr_dop;
    345   1.1  christos 
    346  1.11  christos 	ND_PRINT(" wb-rrep:");
    347  1.11  christos 	if (len < sizeof(*rrep))
    348   1.1  christos 		return (-1);
    349   1.1  christos 	len -= sizeof(*rrep);
    350   1.1  christos 
    351  1.11  christos 	ND_PRINT(" for %s %s:%u<%u:%u>",
    352  1.11  christos 	    GET_IPADDR_STRING(rrep->pr_id),
    353  1.11  christos 	    GET_IPADDR_STRING(dop->pd_page.p_sid),
    354  1.11  christos 	    GET_BE_U_4(dop->pd_page.p_uid),
    355  1.11  christos 	    GET_BE_U_4(dop->pd_sseq),
    356  1.11  christos 	    GET_BE_U_4(dop->pd_eseq));
    357   1.1  christos 
    358   1.4  christos 	if (ndo->ndo_vflag)
    359  1.11  christos 		wb_dops(ndo, dop,
    360  1.11  christos 		        GET_BE_U_4(dop->pd_sseq),
    361  1.11  christos 		        GET_BE_U_4(dop->pd_eseq));
    362   1.1  christos 	return (0);
    363   1.1  christos }
    364   1.1  christos 
    365   1.1  christos static int
    366   1.4  christos wb_drawop(netdissect_options *ndo,
    367   1.4  christos           const struct pkt_dop *dop, u_int len)
    368   1.1  christos {
    369  1.11  christos 	ND_PRINT(" wb-dop:");
    370  1.11  christos 	if (len < sizeof(*dop))
    371   1.1  christos 		return (-1);
    372   1.1  christos 	len -= sizeof(*dop);
    373   1.1  christos 
    374  1.11  christos 	ND_PRINT(" %s:%u<%u:%u>",
    375  1.11  christos 	    GET_IPADDR_STRING(dop->pd_page.p_sid),
    376  1.11  christos 	    GET_BE_U_4(dop->pd_page.p_uid),
    377  1.11  christos 	    GET_BE_U_4(dop->pd_sseq),
    378  1.11  christos 	    GET_BE_U_4(dop->pd_eseq));
    379   1.1  christos 
    380   1.4  christos 	if (ndo->ndo_vflag)
    381  1.11  christos 		wb_dops(ndo, dop,
    382  1.11  christos 		        GET_BE_U_4(dop->pd_sseq),
    383  1.11  christos 		        GET_BE_U_4(dop->pd_eseq));
    384   1.1  christos 	return (0);
    385   1.1  christos }
    386   1.1  christos 
    387   1.1  christos /*
    388   1.1  christos  * Print whiteboard multicast packets.
    389   1.1  christos  */
    390  1.10     kamil UNALIGNED_OK
    391   1.1  christos void
    392   1.4  christos wb_print(netdissect_options *ndo,
    393  1.11  christos          const u_char *hdr, u_int len)
    394   1.1  christos {
    395  1.11  christos 	const struct pkt_hdr *ph;
    396  1.11  christos 	uint8_t type;
    397  1.11  christos 	int print_result;
    398   1.1  christos 
    399  1.11  christos 	ndo->ndo_protocol = "wb";
    400   1.1  christos 	ph = (const struct pkt_hdr *)hdr;
    401  1.11  christos 	if (len < sizeof(*ph))
    402  1.11  christos 		goto invalid;
    403  1.11  christos 	ND_TCHECK_SIZE(ph);
    404   1.1  christos 	len -= sizeof(*ph);
    405   1.1  christos 
    406  1.11  christos 	if (GET_U_1(ph->ph_flags))
    407  1.11  christos 		ND_PRINT("*");
    408  1.11  christos 	type = GET_U_1(ph->ph_type);
    409  1.11  christos 	switch (type) {
    410   1.1  christos 
    411   1.1  christos 	case PT_KILL:
    412  1.11  christos 		ND_PRINT(" wb-kill");
    413   1.1  christos 		return;
    414   1.1  christos 
    415   1.1  christos 	case PT_ID:
    416  1.11  christos 		print_result = wb_id(ndo, (const struct pkt_id *)(ph + 1), len);
    417   1.1  christos 		break;
    418   1.1  christos 
    419   1.1  christos 	case PT_RREQ:
    420  1.11  christos 		print_result = wb_rreq(ndo, (const struct pkt_rreq *)(ph + 1), len);
    421   1.1  christos 		break;
    422   1.1  christos 
    423   1.1  christos 	case PT_RREP:
    424  1.11  christos 		print_result = wb_rrep(ndo, (const struct pkt_rrep *)(ph + 1), len);
    425   1.1  christos 		break;
    426   1.1  christos 
    427   1.1  christos 	case PT_DRAWOP:
    428  1.11  christos 		print_result = wb_drawop(ndo, (const struct pkt_dop *)(ph + 1), len);
    429   1.1  christos 		break;
    430   1.1  christos 
    431   1.1  christos 	case PT_PREQ:
    432  1.11  christos 		print_result = wb_preq(ndo, (const struct pkt_preq *)(ph + 1), len);
    433   1.1  christos 		break;
    434   1.1  christos 
    435   1.1  christos 	case PT_PREP:
    436  1.11  christos 		print_result = wb_prep(ndo, (const struct pkt_prep *)(ph + 1), len);
    437   1.1  christos 		break;
    438   1.1  christos 
    439   1.1  christos 	default:
    440  1.11  christos 		ND_PRINT(" wb-%u!", type);
    441  1.11  christos 		print_result = -1;
    442   1.1  christos 	}
    443  1.11  christos 	if (print_result < 0)
    444  1.11  christos 		goto invalid;
    445  1.11  christos 	return;
    446  1.11  christos 
    447  1.11  christos invalid:
    448  1.11  christos 	nd_print_invalid(ndo);
    449   1.1  christos }
    450