pgmcat/ 40755 423 423 0 7052460115 7657 5ustar luigipgmcat/Makefile100644 423 423 611 7052460231 11371 0ustar luigi# # Makefile for pgmcat # lr 000216 # CC=gcc CCFLAGS=-O -Wall -Wunused LDFLAGS=-O INCS = SRCS = pgmcat.c OBJS = $(SRCS:.c=.o) ALLSRCS = $(INCS) $(SRCS) Makefile # pgmcat.1 .c.o: Makefile $(INCS) $(CC) -c $(CCFLAGS) $*.c all: $(OBJS) $(CC) $(LDFLAGS) $(OBJS) -o pgmcat $(OBJS): depend: clean: rm -f *.o *.core *.*~ *~ pgmcat tgz: tar cvzf pgmcat`date +%y%m%d_%H%M`.tgz $(ALLSRCS) pgmcat/pgmcat.c100644 423 423 14442 7052460210 11414 0ustar luigi/* * pgmcat.c * * pgmcat [-s] [-ttl t] [-bsz blocksize] [ip/port] * * Reads/ writes (with -s) a file from stdout/stdin from/to a pgm socket. * */ #include #include #include /* for bzero */ #include #include /* for readv */ #include /* for close */ #include #include #include #include int verbose = 1 ; int bsz = 1400 ; int ttl = 1 ; char def_addr[] = "224.2.3.4/5678"; void usage() { printf("pgmcat [-s|-j|-bsz N| -t ttl] ip/port\n"); exit(0); } void err_quit(char *s) { fprintf(stderr, "%s\n", s); exit(1); } int sender = 0 ; struct in_addr dst_addr ; u_int16_t dport ; int do_join=0; /* default */ void find_tsi(int s, u_int16_t *sport, u_int32_t *gsid_low, u_int16_t *gsid_high) { struct pgmhdr pgm_header; for (;;) { int numread = read(s, &pgm_header, sizeof(pgm_header)); if (numread <0) err_quit("find_tsi error reading"); if (numread < sizeof(struct pgmhdr)) { fprintf(stderr, "-- short read %d\n", numread); } else { *sport = pgm_header.ph_sport; *gsid_low = pgm_header.gsid_low ; *gsid_high = pgm_header.gsid_high ; return ; } } } int rx_open(struct in_addr ip_dest, u_int16_t dport, u_int16_t sport, u_int32_t gsid_low, u_int16_t gsid_high) { struct sockaddr_pgm sin; int op ; int s; struct ip_mreq mr; s = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_PGM); if (s < 0) err_quit("can't create pgm socket"); op = 1 ; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &op, sizeof(op)) < 0) err_quit("can't set SO_REUSEADDR"); if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &op, sizeof(op)) < 0) err_quit("can't set SO_REUSEPORT"); if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &op, sizeof(op)) < 0) err_quit("can't set IP_MULTICAST_LOOP"); bzero((char *)&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr = ip_dest; /* commit as sender, gsi == 0, sin_port == sport */ sin.sin_port = dport ; sin.gsid_low = gsid_low; sin.gsid_high = gsid_high; sin.sport = sport; if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { sin.sin_addr.s_addr = INADDR_ANY; if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) err_quit("rx_bind error"); } mr.imr_multiaddr = ip_dest; /* IP mc addr of group */ mr.imr_interface.s_addr = INADDR_ANY; /* IP uc addr of local interface */ if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr) ) <0) err_quit("rx_join error"); return s ; } int tx_open(struct in_addr ip_dest, u_int16_t dport, int ttl, int do_join) { struct sockaddr_pgm sin; int op ; int s; s = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_PGM); if (s < 0) err_quit("can't create pgm socket"); op = 1 ; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &op, sizeof(op)) < 0) err_quit("can't set SO_REUSEADDR"); if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &op, sizeof(op)) < 0) err_quit("can't set SO_REUSEPORT"); if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &op, sizeof(op)) < 0) err_quit("can't set IP_MULTICAST_LOOP"); if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) err_quit("can't set IP_MULTICAST_TTL"); bzero((char *)&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; #if 0 /* to bind the sender's sport, gsi == 0, sin_port == sport */ sin.sport = sin.sin_port = htons(sport); sin.gsid_low = 0; sin.gsid_high = 0; if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) err_quit("tx_bind error"); #endif /* connect, this is a sender. */ sin.sin_addr = ip_dest; sin.sin_port = dport; if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) err_quit("tx_connect error"); op = TRAIL_ADVANCE_DATA; if (setsockopt(s, IPPROTO_PGM, PGM_TRAIL_ADVANCE, &op, sizeof(op) ) < 0 ) err_quit("can't set TRAIL_ADVANCE_DATA"); if (do_join) { op = 1; if (setsockopt(s, IPPROTO_PGM, PGM_OPT_JOIN, &op, sizeof(op) ) < 0 ) err_quit("can't set PGM_OPT_JOIN"); } return s ; } int main(int argc, char *argv[]) { char *p, *p0; int s; char buf[65536]; /* * parse options */ while (argc > 1 && *(p = argv[1]) == '-') { argc-- ; argv++ ; if (!strcmp(p, "-s")) { sender = 1 ; } else if (!strcmp(p, "-j")) { do_join = 1 ; } else if (!strcmp(p, "-bsz")) { if (argc < 2) usage(); bsz = atoi(argv[1]); argc -- ; argv++ ; } else if (!strcmp(p, "-ttl")) { if (argc < 2) usage(); ttl = atoi(argv[1]); if (ttl < 1 || ttl > 255) usage(); argc -- ; argv++ ; } } if (argc > 1) p0 = argv[1]; else { p0 = def_addr ; fprintf(stderr, "using default address %s\n", p0); } for (p = p0; *p == '.' || (*p >='0' && *p <= '9') ; p++) ; if (*p != '/') usage(); *p = '\0'; dst_addr.s_addr = inet_addr(p0); dport = htons(atoi(p+1)); if (verbose) fprintf(stderr, "%s %s/%d\n", sender ? "TX to" : "RX from", inet_ntoa(dst_addr), ntohs(dport) ); if (sender) { int l ; long tot_w = 0 ; s = tx_open(dst_addr, dport, ttl, do_join); sleep(5); /* time for some SPM */ while ( (l = read(0, buf, bsz)) > 0 ) { l = write(s, buf, l); tot_w += l ; if (verbose) fprintf(stderr, "write %ld\n", tot_w); } shutdown(s, SHUT_WR); sleep(15); /* wait for data flush ? */ } else { u_int32_t gsid_low = 0; u_int16_t gsid_high = 0, sport = 0; long tot_r = 0 ; /* raw, begin the TSI 0 */ s = rx_open(dst_addr, dport, sport, gsid_low, gsid_high); find_tsi(s, &sport, &gsid_low, &gsid_high); if (verbose) fprintf(stderr, "GSI: 0x%08lx.%04x.%04x\n", ntohl(gsid_low), ntohs(gsid_high), ntohs(sport) ); close(s); /* now full socket */ s = rx_open(dst_addr, dport, sport, gsid_low, gsid_high); while (1) { int l ; l = read(s, buf, sizeof(buf)); if (l > 0) { write(1, buf, l); tot_r += l ; if (verbose) fprintf(stderr, "read %d %d\n", l, tot_r); } else { /* zero read means hole */ int o, olen = sizeof(o); if (getsockopt(s, IPPROTO_PGM, PGM_HOLE_SIZE, &o, &olen) < 0 ) err_quit("can't get PGM_HOLE_SIZE"); if (o == -1) /* FIN */ break ; if (verbose) fprintf(stderr, "at %ld read %d, hole size %d\n", tot_r, l, o); } } } return 0 ; }