--- interface.h.orig Sun Nov 21 11:51:25 1999 +++ interface.h Fri Jan 7 12:07:19 2000 @@ -67,7 +67,7 @@ * In particular, it allows for an ethernet header, tcp/ip header, and * 14 bytes of data (assuming no ip options). */ -#define DEFAULT_SNAPLEN 68 +#define DEFAULT_SNAPLEN 80 /* for pgm, need at least 74 */ #ifndef BIG_ENDIAN #define BIG_ENDIAN 4321 --- print-ip.c.orig Tue Sep 15 21:46:59 1998 +++ print-ip.c Fri Jan 7 12:07:19 2000 @@ -417,6 +417,13 @@ icmp_print(cp, (const u_char *)ip); break; +#ifndef IPPROTO_PGM +#define IPPROTO_PGM 113 +#endif + case IPPROTO_PGM: + pgm_print(cp, len, (const u_char *)ip); + break; + #ifndef IPPROTO_IGRP #define IPPROTO_IGRP 9 #endif --- print-udp.c.orig Tue Sep 15 21:46:59 1998 +++ print-udp.c Fri Jan 7 16:05:39 2000 @@ -446,3 +446,287 @@ } else (void)printf(" udp %u", (u_int32_t)(ulen - sizeof(*up))); } + +#if 1 +/* + * this code does the printing of pgm packets + * Nov. 1999 - Universita` di Pisa + */ +typedef u_int32_t pgm_seq ; + +struct pgmhdr { + u_int16_t ph_sport ; + u_int16_t ph_dport ; + u_int8_t type ; +#define PGM_SPM_TYPE 0 +#define PGM_OD_TYPE 4 +#define PGM_RD_TYPE 5 +#define PGM_NAK_TYPE 8 +#define PGM_NNAK_TYPE 9 +#define PGM_NCF_TYPE 10 +#define PGM_ACK_TYPE 11 /* for cong.control */ + + u_int8_t options ; +#define PGM_OPT_PRESENT 1 /* there are option extentions */ +#define PGM_OPT_NE_PRESENT 2 /* there are NE-significant opt.ext. */ + + u_int16_t checksum ; + u_int32_t gsid_low ; + u_int16_t gsid_high ; + u_int16_t tsdu_len ; + /* + * all packets have a couple of sequence numbers here, but + * their meaning differs. + */ + pgm_seq _seq1; +#define od_txw_trail _seq1 /* this is in ODATA pkts */ +#define spm_seq _seq1 /* this is in SPM pkts */ +#define nak_req_seq _seq1 /* this is in NAK pkts */ +#define ack_req_seq _seq1 /* this is in ACK pkts */ + + pgm_seq _seq2; +#define od_dp_seq _seq2 /* this is in ODATA pkts */ +#define spm_txw_trail _seq2 /* this is in SPM pkts */ +#define ack_rxw_lead _seq2 /* this is in ACK pkts */ +} ; + +/* + * Source Path Message (SPM) packets + */ + +struct pgm_spm_body { + u_int32_t spm_le_seq ; + u_int16_t nla_afi ; + u_int16_t rsvd ; + struct in_addr path_nla ; + u_char options[0]; +} ; + +struct pgm_spm { + struct pgmhdr pgmhdr ; + struct pgm_spm_body body ; +} ; + +/* + * (N)ACK packets (from receivers/DLR) + */ +struct pgm_nack_body { + /* + u_int32_t req_seq ; + u_int16_t nla_afi ; + u_int16_t rsvd1 ; + */ + struct in_addr src_nla ; + u_int16_t nla_afi2 ; + u_int16_t rsvd2 ; + struct in_addr mc_nla ; + u_char options[0] ; +} ; + +/* + * ACK packets (from elected receivers) + */ +struct pgm_ack_body { + /* + u_int32_t req_seq ; + u_int16_t nla_afi ; + u_int16_t rsvd1 ; + */ + u_int32_t ack_bitmask ; +} ; +#if 1 +/* + * options (similar to IP options) + */ +#define OPT_HLEN sizeof(struct pgm_option) + +struct pgm_option { + u_int8_t type; + u_int8_t len; + u_int16_t tot_len; +}; +/* + * PGM options. The same names, in some cases, are also used + * as parameter names in set/getsockopt. + * Most options are unimplemented as of 990928 + */ +#define PGM_OPT_LENGTH 0x00 +#define PGM_OPT_FRAGMENT 0x01 +#define PGM_OPT_JOIN 0x03 +#define PGM_OPT_TIME 0x04 +#define PGM_OPT_RXQ 0x05 +#define PGM_OPT_DROP 0x06 +#define PGM_OPT_REDIRECT 0x07 + +#define PGM_OPT_LOSSRATE 0x10 +#define PGM_OPT_SEND_NAK 0x11 /* receivers, please send a NAK */ +#define PGM_OPT_ELECT 0x12 /* node X is elected as acker */ +#define PGM_OPT_SYN 0x21 +#define PGM_OPT_FIN 0x22 + +#define PGM_OPT_MASK 0x7f + +#define PGM_OPT_END 0x80 /* end of options marker */ + +/* experimental options */ +#define PGM_OPT_LOSSRATE 0x10 +#define PGM_OPT_DESC 0x20 +#define PGM_OPT_SYN 0x21 +#define PGM_OPT_FIN 0x22 + +#endif + +void +pgm_print(register const u_char *bp, u_int length, register const u_char *bp2) +{ + const struct pgmhdr *pp; /* pgm header */ + const struct ip *ip; + const u_char *cp; + const u_char *ep = bp + length; + u_short sport, dport, ulen; + int slen, hlen = 0 ; + char *s, buf[16]; + + hlen = sizeof(struct pgmhdr) ; /* header at least this long */ + slen = snapend - bp ; /* have this many bytes in the snap */ + slen -= hlen ; /* less the header... */ + if (slen < 0) { /* not enough data to print the header */ + printf("[|pgm]"); + return; + } + if (ep > snapend) + ep = snapend; + pp = (struct pgmhdr *)bp; + ip = (struct ip *)bp2; + cp = (u_char *)(pp + 1 ); + + sport = ntohs(pp->ph_sport); + dport = ntohs(pp->ph_dport); + ulen = ntohs(pp->tsdu_len); + (void)printf("%s.%s > %s.%s: GSI 0x%04x%02x len %d ", + ipaddr_string(&ip->ip_src), + udpport_string(sport), + ipaddr_string(&ip->ip_dst), + udpport_string(dport), + ntohl(pp->gsid_low), + ntohs(pp->gsid_high), + ulen ); + /* now process pieces after fixed header */ + switch( pp->type ) { + case PGM_SPM_TYPE: { + struct pgm_spm_body *b = (struct pgm_spm_body *)(cp) ; + if (slen < sizeof (*b) ) { + printf("[|spm-body]"); + return ; + } + printf( "SPM %u path %s", + ntohl(pp->spm_seq), + ipaddr_string( &(b->path_nla.s_addr) ) ); + cp = (u_char *)(b+1); + } + break ; + + case PGM_OD_TYPE: + case PGM_RD_TYPE: + printf( "%s %u trail %u", + pp->type == 4 ? "ODATA" : "RDATA" , + ntohl(pp->od_dp_seq), + ntohl(pp->od_txw_trail) ); + break ; + + case PGM_NAK_TYPE: + case PGM_NCF_TYPE: { + struct pgm_nack_body *b= (struct pgm_nack_body *)(cp) ; + if (slen < sizeof (*b) ) { + printf("[|nak/ncf-body]"); + return ; + } + printf( "%s %u src %s mc %s", + pp->type == 8 ? "NAK" : "NCF" , + ntohl(pp->nak_req_seq), + ipaddr_string( &(b->src_nla.s_addr) ), + ipaddr_string( &(b->mc_nla.s_addr) ) + ); + cp = (u_char *)(b+1); + } + break ; + + case PGM_ACK_TYPE: { + struct pgm_ack_body *b= (struct pgm_ack_body *)(cp) ; + if (slen < sizeof (*b) ) { + printf("[|ack-body]"); + return ; + } + printf( "ACK %u lead %u mask %08x", + ntohl(pp->ack_req_seq), + ntohl(pp->ack_rxw_lead), + ntohl(b->ack_bitmask) + ); + cp = (u_char *)(b+1); + } + break ; + + default: + printf("UNRECOGNIZED TYPE 0x%02x\n", pp->type); + return ; + } + if (pp->options & PGM_OPT_PRESENT) { + struct pgm_option *o = (struct pgm_option *)cp ; + if (slen < 4) { /* minimal option len */ + printf("[Ioptions]"); + return ; + } + while (cp+4 <= ep) { + o = (struct pgm_option *)cp ; + switch (o->type & PGM_OPT_MASK) { + case PGM_OPT_LENGTH: + printf(" OPT[%d] %d ", o->len, ntohs(o->tot_len) ); + break ; + case PGM_OPT_JOIN: + if (o->len != 8 || cp+8 > ep) { + printf("[|join]"); + } else { + u_int32_t *p = (u_int32_t *)(cp+4); + printf("join %d ", ntohl(*p) ); + } + break ; + case PGM_OPT_LOSSRATE: + if (o->len != 16 || cp+16 > ep) { + printf("[|lossrate]"); + } else { + u_int32_t *p = (u_int32_t *)(cp+4); + printf("loss %0.6f ", (double)(1.0*ntohl(*p)/65536) ); + printf("lead %d ", ntohs(p[1]) ); + printf("recv %s ", ipaddr_string( p+2 ) ); + } + break ; + case PGM_OPT_SEND_NAK: + if (o->len != 8 || cp+8 > ep) { + printf("[|send_nak]"); + } else { + u_int32_t *p = (u_int32_t *)(cp+4); + printf("send_nak %s ", ipaddr_string( p ) ); + } + break ; + case PGM_OPT_ELECT: + if (o->len != 8 || cp+8 > ep) { + printf("[|elect]"); + } else { + u_int32_t *p = (u_int32_t *)(cp+4); + printf("elect %s ", ipaddr_string( p ) ); + } + break ; + default: + printf("OPT_%d [%d] ", o->type, o->len); + break ; + } + if (o->len < 4) + cp += 4 ; /* malformed opt, avoid infinite loop */ + else + cp += o->len ; + if (o->type & PGM_OPT_END) + return ; + } + } +} +#endif