www.pudn.com > Source_program.rar > NETUTIL.C
#include#include #include #include #include #include #include "netutil.h" #include "net.h" #include "ether.h" #define CFGDELIMS " \t\r\n" /* Config item delimiters */ #define MAXCFGLINE 90 /* Max length of line in CFG file */ BYTE bcast[MACLEN] = {BCASTADDR}; /* Broadcast MAC addr */ BYTE zermac[MACLEN]; /* All-zero MAC addr */ extern int netdebug; /* Net packet display flags */ #if WIN32 long dir_handle=-1L; struct _finddata_t dir_block; #else struct ffblk dir_block; #endif /* Return maximum length of the given frame */ int getframe_maxlen(GENFRAME *gfp) { return(gfp->g.dtype&DTYPE_ETHER ? MAXFRAME : MAXSLIP); } /* Return the Maximum Transmission Unit (i.e. data size) for the given frame */ WORD getframe_mtu(GENFRAME *gfp) { WORD mtu; mtu = (WORD)getframe_maxlen(gfp); if (gfp->g.dtype & DTYPE_ETHER) { mtu -= sizeof(ETHERHDR); if (gfp->g.dtype & DTYPE_SNAP) mtu -= sizeof(SNAPHDR); } return(mtu); } /* Return frame header length, given driver type */ WORD dtype_hdrlen(WORD dtype) { return(dtype&DTYPE_ETHER ? sizeof(ETHERHDR) : 0); } /* Get pointer to the data area of the given frame */ void *getframe_datap(GENFRAME *gfp) { return(&gfp->buff[dtype_hdrlen(gfp->g.dtype)]); } /* Get pointer to the source address of the given frame, 0 if none */ BYTE *getframe_srcep(GENFRAME *gfp) { ETHERHDR *ehp; BYTE *srce=0; if (gfp->g.dtype & DTYPE_ETHER) /* Only Ethernet has address */ { ehp = (ETHERHDR *)gfp->buff; srce = ehp->srce; } return(srce); } /* Copy the source MAC addr of the given frame; use broadcast if no addr */ BYTE *getframe_srce(GENFRAME *gfp, BYTE *buff) { BYTE *p; p = getframe_srcep(gfp); if (p) memcpy(buff, p, MACLEN); else memcpy(buff, bcast, MACLEN); return(p); } /* Get pointer to the destination address of the given frame, 0 if none */ BYTE *getframe_destp(GENFRAME *gfp) { ETHERHDR *ehp; BYTE *dest=0; if (gfp->g.dtype & DTYPE_ETHER) /* Only Ethernet has address */ { ehp = (ETHERHDR *)gfp->buff; dest = ehp->dest; } return(dest); } /* Copy the destination MAC addr of the given frame; use broadcast if no addr */ BYTE *getframe_dest(GENFRAME *gfp, BYTE *buff) { BYTE *p; p = getframe_destp(gfp); if (p) memcpy(buff, p, MACLEN); else memcpy(buff, bcast, MACLEN); return(p); } /* Get the protocol for the given frame; if unknown , return 0 */ WORD getframe_pcol(GENFRAME *gfp) { ETHERHDR *ehp; WORD pcol=0; if (gfp->g.dtype & DTYPE_ETHER) /* Only Ethernet has protocol */ { ehp = (ETHERHDR *)gfp->buff; pcol = ehp->ptype; } return(pcol); } /* Return non-zero if frame has a broadcast address */ int is_bcast(GENFRAME *gfp) { return(gfp->g.dtype&DTYPE_ETHER && !memcmp(gfp->buff, bcast, MACLEN)); } /* Check Ethernet frame, given frame pointer & length, return non-0 if OK */ int is_ether(GENFRAME *gfp, int len) { int dlen=0; if (gfp && (gfp->g.dtype & DTYPE_ETHER) && len>=sizeof(ETHERHDR)) { dlen = len - sizeof(ETHERHDR); swap_ether(gfp); } return(dlen); } /* Make a frame, given data length. Return length of complete frame ** If Ethernet, set dest addr & protocol type; if SLIP, ignore these */ int make_frame(GENFRAME *gfp, BYTE dest[], WORD pcol, WORD dlen) { ETHERHDR *ehp; if (gfp->g.dtype & DTYPE_ETHER) { ehp = (ETHERHDR *)gfp->buff; ehp->ptype = pcol; memcpy(ehp->dest, dest, MACLEN); swap_ether(gfp); dlen += sizeof(ETHERHDR); } return(dlen); } /* Byte-swap an Ethernet frame, return header length */ void swap_ether(GENFRAME *gfp) { ETHERFRAME *efp; efp = (ETHERFRAME *)gfp->buff; efp->h.ptype = swapw(efp->h.ptype); } /* Check SLIP frame, return non-zero if OK */ int is_slip(GENFRAME *gfp, int len) { return((gfp->g.dtype & DTYPE_SLIP) && len>0); } /* Display SLIP or Ethernet frame (must be in network byte order) */ void disp_frame(GENFRAME *gfp, int dlen, int tx) { char temps[20]; BYTE *data, pcol; WORD type=0x0800; int i; printf(tx ? "Tx%u /" : "Rx%u \\", gfp->g.dtype & NETNUM_MASK); printf("len %u ", dlen); data = (BYTE *)getframe_datap(gfp); if (netdebug & 1) /* Verbose display? */ { if (gfp->g.dtype & DTYPE_ETHER) { printf("%s ", ethstr(&gfp->buff[tx ? 0 : MACLEN], temps)); type = swapw(*(WORD *)&gfp->buff[MACLEN*2]); if (type == 0x0806) { printf("ARP %s ", ipstr(swapl(*(long *)&data[14]), temps)); printf("-> %s ", ipstr(swapl(*(long *)&data[24]), temps)); } } else printf("------SLIP------- "); if (type == 0x0800) { printf("IP %s ", ipstr(swapl(*(long *)&data[12]), temps)); printf("-> %s ", ipstr(swapl(*(long *)&data[16]), temps)); pcol = *(data+9); printf(pcol==1 ? "ICMP" : pcol==6 ? "TCP" : pcol==17 ? "UDP" : ""); } printf("\n"); } if (netdebug & 2) /* Hex display? */ { for (i=0; i >24)&255,(ip>>16)&255,(ip>>8)&255,ip&255); return(s); } /* Convert Ethernet address into a string (max 17 chars plus null) */ char *ethstr(BYTE *addr, char *str) { int i; char *s=str; if (!memcmp(addr, bcast, MACLEN)) strcpy(s, "----BROADCAST----"); else for (i=0; i 0 ? ":%02x" : "%02x", *addr++); return(str); } /* Convert string to IP addr: first digits form most-significant byte */ LWORD atoip(char *str) { LWORD ip=0L; int i=4, n; char c=1; while (--i>=0 && c) { n = 0; while (isdigit(c=*str++)) n = n*10 + c-'0'; ip += (LWORD)n << (i*8); } return(ip); } /* Retrieve the integer value of a config item. Return 0 if not found */ int read_cfgval(char *fname, char *item, int *valp) { char str[10]; int ok=0; if ((ok = read_cfgstr(fname, item, str, sizeof(str)-1)) != 0) { if (valp) *valp = atoi(str); } return(ok); } /* Return the config string for the given item. Return 0 if not found */ int read_cfgstr(char *fname, char *item, char *dest, int destlen) { return(read_cfgstr_n(fname, 0, item, dest, destlen)); } /* Return the config string for the n'th item (1st item if n=0). ** Return 0 if not found */ int read_cfgstr_n(char *fname, int n, char *item, char *dest, int destlen) { FILE *in; int ok=-1, len; char *s, buff[MAXCFGLINE]; if ((in=fopen(fname, "rt")) != 0) /* Open as text file */ { /* Read a line at a time */ while (ok =n); } /* Return non-zero if config item has option set (or 'all' options set) */ int read_cfgopt(char *fname, char *item, char *opt) { char *s, buff[MAXCFGLINE]; int n, ok=0; if (read_cfgstr(fname, item, buff, MAXCFGLINE-1)) { s = buff; while (!ok && *s) { n = strcspn(s, CFGDELIMS); /* Get length of next option */ ok = !strncmp(s, opt, n) || !strncmp(s, "all", n); s = skippunct(s + n); /* Match option, skip to next */ } } return(ok); } /* Check the given token is at the start of the string ** Return pointer to the first char after the token, 0 if token not found */ char *skiptoken(char *str, char *tok) { int n; char *s=0; n = strlen(tok); if (n>0 && str && !strnicmp(str, tok, n)) s = str + n; return(s); } /* Return a pointer to the first char after any whitespace */ char *skipspace(char *str) { while (isspace(*str)) str++; return(str); } /* Return a pointer to the first char after any whitespace or punctuation */ char *skippunct(char *str) { while (isspace(*str) || ispunct(*str)) str++; return(str); } /* Check whether a sequence value lies within two others, return 0 if not */ int in_limits(LWORD val, LWORD lo, LWORD hi) { long lodiff, hidiff; lodiff = val - lo; hidiff = hi - val; return(lodiff>=0 && hidiff>=0); } /* Return total length of data in buffer */ WORD buff_dlen(CBUFF *bp) { return((WORD)((bp->in - bp->out) & (bp->len - 1))); } /* Return length of untried (i.e. unsent) data in buffer */ WORD buff_untriedlen(CBUFF *bp) { return((WORD)((bp->in - bp->trial) & (bp->len - 1))); } /* Return length of trial data in buffer (i.e. data sent but unacked) */ WORD buff_trylen(CBUFF *bp) { return((WORD)((bp->trial - bp->out) & (bp->len - 1))); } /* Return length of free space in buffer */ WORD buff_freelen(CBUFF *bp) { return(bp->len ? bp->len - 1 - buff_dlen(bp) : 0); } /* Set all the buffer pointers to a starting value */ void buff_setall(CBUFF *bp, LWORD start) { bp->out = bp->in = bp->trial = start; } /* Rewind the trial pointer by the given byte count, return actual count */ WORD buff_retry(CBUFF *bp, WORD len) { len = minw(len, buff_trylen(bp)); bp->trial -= len; return(len); } /* Pre-load data into buffer, i.e. copy into the given buffer location ** Check that existing data isn't overwritten, return byte count if OK. ** If data pointer is null, do check but don't transfer data */ WORD buff_preload(CBUFF *bp, LWORD oset, BYTE *data, WORD len) { WORD in, n=0, n1, n2, free; long inoff; inoff = oset - bp->in; /* Offset of data from I/P ptr */ in = (WORD)oset & (bp->len-1); /* Mask I/P ptr to buffer area */ free = buff_freelen(bp); /* Free space in buffer */ if (inoff>=0 && inoff<(free)) /* If start is in free space.. */ { n = minw(len, free); /* Get max allowable length */ n1 = minw(n, (WORD)(bp->len - in)); /* Length up to end of buff */ n2 = n - n1; /* Length from start of buff */ if (n1 && data) /* If anything to copy.. */ memcpy(&bp->data[in], data, n1);/* ..copy up to end of buffer.. */ if (n2 && data) /* ..and maybe also.. */ memcpy(bp->data, &data[n1], n2);/* ..copy into start of buffer */ } return(n); } /* Load data into buffer, return byte count that could be accepted ** If data pointer is null, adjust pointers but don't transfer data */ WORD buff_in(CBUFF *bp, BYTE *data, WORD len) { WORD in, n, n1, n2; in = (WORD)bp->in & (bp->len-1); /* Mask I/P ptr to buffer area */ n = minw(len, buff_freelen(bp)); /* Get max allowable length */ n1 = minw(n, (WORD)(bp->len - in)); /* Length up to end of buff */ n2 = n - n1; /* Length from start of buff */ if (n1 && data) /* If anything to copy.. */ memcpy(&bp->data[in], data, n1); /* ..copy up to end of buffer.. */ if (n2 && data) /* ..and maybe also.. */ memcpy(bp->data, &data[n1], n2); /* ..copy into start of buffer */ bp->in += n; /* Bump I/P pointer */ return(n); } /* Load string into buffer, return num of chars that could be accepted */ WORD buff_instr(CBUFF *bp, char *str) { return(buff_in(bp, (BYTE *)str, (WORD)strlen(str))); } /* Load file into buffer, return byte count */ WORD buff_infile(CBUFF *bp, FILE *fp, WORD len) { WORD in, n, n1, n2=0; int count=0; in = (WORD)bp->in & (bp->len-1); /* Mask I/P ptr to buffer area */ n = minw(len, buff_freelen(bp)); /* Get max allowable length */ n1 = minw(n, (WORD)(bp->len - in)); /* Length up to end of buff */ if (n1) /* If anything to read.. */ { /* ..get 1st block from file */ count = fread(&bp->data[in], 1, n1, fp); n2 = len data, 1, n2, fp); bp->in += count; /* Bump I/P pointer */ return((WORD)count); } /* Remove trial data from buffer, return byte count. ** If data pointer is null, adjust pointers but don't transfer data */ WORD buff_try(CBUFF *bp, BYTE *data, WORD maxlen) { WORD trial, n, n1, n2; trial = (WORD)bp->trial & (bp->len-1); /* Mask trial ptr to buffer area */ n = minw(maxlen, buff_untriedlen(bp)); /* Get max allowable length */ n1 = minw(n, (WORD)(bp->len - trial)); /* Length up to end of buff */ n2 = n - n1; /* Length from start of buff */ if (n1 && data) /* If anything to copy.. */ memcpy(data, &bp->data[trial], n1); /* ..copy up to end of buffer.. */ if (n2 && data) /* ..and maybe also.. */ memcpy(&data[n1], bp->data, n2); /* ..copy from start of buffer */ bp->trial += n; /* Bump trial pointer */ return(n); } /* Remove data from buffer, return byte count ** If data pointer is null, adjust pointers but don't transfer data */ WORD buff_out(CBUFF *bp, BYTE *data, WORD maxlen) { WORD out, n, n1, n2; out = (WORD)bp->out & (bp->len-1); /* Mask O/P ptr to buffer area */ n = minw(maxlen, buff_dlen(bp)); /* Get max allowable length */ n1 = minw(n, (WORD)(bp->len - out)); /* Length up to end of buff */ n2 = n - n1; /* Length from start of buff */ if (n1 && data) /* If anything to copy.. */ memcpy(data, &bp->data[out], n1); /* ..copy up to end of buffer.. */ if (n2 && data) /* ..and maybe also.. */ memcpy(&data[n1], bp->data, n2); /* ..copy from start of buffer */ bp->out += n; /* Bump O/P pointer */ if (buff_untriedlen(bp) > buff_dlen(bp))/* ..and maybe trial pointer */ bp->trial = bp->out; return(n); } /* Return length of null-delimited string in buffer, 0 if no null terminator */ WORD buff_strlen(CBUFF *bp) { return(buff_chrlen(bp, 0)); } /* Return length of string in buffer given delimiter char, 0 if no match */ WORD buff_chrlen(CBUFF *bp, char c) { WORD out, n, n1, n2; BYTE *p, *q=0; out = (WORD)bp->out & (bp->len-1); /* Mask O/P ptr to buffer area */ n = buff_dlen(bp); /* Get max length */ n1 = minw(n, (WORD)(bp->len - out)); /* Length up to end of buff */ n2 = n - n1; /* Length from start of buff */ if (n1) /* Check up to end of buffer */ q = memchr(p=&bp->data[out], c, n1); if (!q && n2) q = memchr(p=bp->data, c, n2); /* ..check data at buffer start */ else n1 = 0; return(q ? (WORD)(q - p) + n1 : 0); } /* Do TCP-style checksum. Improved algorithm is from RFC 1071 */ WORD csum(void *dp, WORD count) { register LWORD total=0L; register WORD n, *p, carries; n = count / 2; p = (WORD *)dp; while (n--) total += *p++; if (count & 1) total += *(BYTE *)p; while ((carries=(WORD)(total>>16))!=0) total = (total & 0xffffL) + carries; return((WORD)total); } /* Safe versions of the min() & max() macros for use on re-entrant code ** Ensures that any function arguments aren't called twice */ WORD minw(WORD a, WORD b) { return(ab ? a : b); } int mini(int a, int b) { return(ab ? a : b); } /* Return byte-swapped word */ WORD swapw(WORD w) { return(((w<<8)&0xff00) | ((w>>8)&0x00ff)); } /* Return byte-swapped longword */ LWORD swapl(LWORD lw) { return(((lw<<24)&0xff000000L) | ((lw<<8 )&0x00ff0000L) | ((lw>>8 )&0x0000ff00L) | ((lw>>24)&0x000000ffL)); } /* Check for timeout on a given tick counter, return non-zero if true */ int timeout(WORD *timep, int sec) { WORD tim, diff; int tout=0; tim = (WORD)time(0); diff = tim - *timep; if (sec==0 || diff>=sec) { *timep = tim; tout = 1; } return(tout); } /* Check for timeout on a given tick counter, return non-zero if true */ int mstimeout(LWORD *timep, int msec) { LWORD tim; long diff; int tout=0; tim = mstime(); diff = tim - *timep; if (msec==0 || diff>=msec) { *timep = tim; tout = 1; } return(tout); } #ifndef WIN32 /* Return approximate millisecond count (DOS only) */ LWORD mstime(void) { return(biostime(0, 0) * 55L); /* Should be 54.945! */ } #endif /* Crude delay in case delay() isn't in the C library ** Derives timing from I/O cycles accessing the interrupt controller ** Slow CPUs (sub-100MHz) will be significantly slower than the given time */ void msdelay(WORD millisec) { int n; while (millisec--) { for (n=0; n<1500; n++) inp(0x61); } } /* Print a hex dump of a buffer */ void hexdump(BYTE *buff, WORD len) { BYTE c, str[17]; WORD j, n=0; while (n < len) /* For each line of 16 bytes... */ { printf(" %04x:", n); for (j=0; j<16; j++) /* For each byte of 16... */ { printf("%c", j==8 ? '-':' '); /* Put '-' after 8 bytes */ if (n++ >= len) /* If no bytes left... */ { printf(" "); /* Fill out space */ str[j] = 0; } else /* If bytes left... */ { printf("%02x", c = *buff++);/* Print byte value */ str[j] = c>=' '&&c<='~' ? c : '.'; } /* Save char if valid */ } str[j] = 0; /* Print char string */ printf(" %s\n", str); } } /* Directory 'findfirst' for both DOS and Win32; returns string, or null */ char *find_first(char *path) { #if WIN32 if (dir_handle != -1L) _findclose(dir_handle); return((dir_handle=_findfirst(path, &dir_block))!=-1L ? dir_block.name : 0); #else return(findfirst(path, &dir_block, 0)==0 ? dir_block.ff_name : 0); #endif } /* Directory 'findnext' for both DOS and Win32; returns string, or null */ char *find_next(void) { #if WIN32 char *s=0; if (_findnext(dir_handle, &dir_block)==0) s = dir_block.name; else { _findclose(dir_handle); dir_handle = -1L; } return(s); #else return(findnext(&dir_block)==0 ? dir_block.ff_name : 0); #endif } /* Return the length of a file that has been found */ long find_filesize(void) { #if WIN32 return(dir_block.size); #else return(dir_block.ff_fsize); #endif } /* EOF */