static void do_dial (const char *value) { int rc = slip_dial (value); if (rc == -1) outsnl (_LANG("Modem not responding\7")); if (rc == -2) outsnl (_LANG("Connect failed")); }
void ReadHostFile (const char *fname) { if (!fname || !*fname) return; hostFname = strdup (fname); if (!hostFname) return; sethostent (1); if (!hostFile) return; while (1) { struct _hostent h; if (!_gethostent(&h)) break; if (!tree_insert(&host_root, (void*)&h, sizeof(h), (CmpFunc)host_cmp_name)) { outsnl (_LANG("Hostfile too big!\7")); break; } } atexit (endhostent); }
/** * Handle incoming PPPoE packets. */ int pppoe_handler (const pppoe_Packet *pkt) { const BYTE *buf; const void *src; const void *dst; WORD proto, len; BOOL bcast, delivered = FALSE; if (pkt->type != 1 || pkt->ver != 1) return (0); src = MAC_SRC (pkt); dst = MAC_DST (pkt); proto = MAC_TYP (pkt); bcast = !memcmp (dst, _eth_brdcast, _eth_mac_len); if (proto == PPPOE_SESS_TYPE && state == StateSession) { if (pkt->code == PPPOE_CODE_SESS && pkt->session == session && !bcast && !memcmp(dst, _eth_addr, _eth_mac_len) && /* to us? */ !memcmp(src, ac_macAddr, _eth_mac_len)) { len = intel16 (pkt->length); buf = &pkt->data[0]; ppp_input (buf, len); /* assume ppp_input() traces it */ delivered = TRUE; } } else if (!bcast && proto == PPPOE_DISC_TYPE && state == StateDiscovery) { if (pkt->code == PPPOE_CODE_PADO) /* Offer (can this be bcast?) */ { got_PADO = TRUE; memcpy (ac_macAddr, src, _eth_mac_len); } else if (pkt->code == PPPOE_CODE_PADT && /* Terminate */ pkt->session == session) { if (cfg.trace) outsnl (_LANG("PPPoE: session terminated")); got_PADT = TRUE; session = 0; } else if (pkt->code == PPPOE_CODE_PADS) /* Session-confirmation */ { got_PADS = TRUE; session = pkt->session; } else if (pkt->code == PPPOE_CODE_PADM) /* Message (what to do?) */ { got_PADM = TRUE; } } if (!delivered) DEBUG_RX (NULL, pkt); return (1); }
int sock_recv_from (udp_Socket *s, DWORD *hisip, WORD *hisport, char *buffer, int len, int peek) { tcp_Socket *t; recv_buf *p; recv_data *r = (recv_data*) s->rdata; int i; if (r->recv_sig != RECV_USED) return (-1); switch (s->ip_type) { case UDP_PROTO: p = (recv_buf*) r->recv_bufs; /* find a used buffer */ for (i = 0; i < r->recv_bufnum; i++, p++) { switch (p->buf_sig) { case RECV_UNUSED: break; case RECV_USED: if (p->buf_len < 0) /* a 0-byte probe packet */ len = -1; else { len = min (p->buf_len, len); memcpy (buffer, p->buf_data, len); } if (hisip) *hisip = p->buf_hisip; if (hisport) *hisport = p->buf_hisport; if (!peek) p->buf_sig = RECV_UNUSED; return (len); default: outsnl (_LANG("ERROR: sock_recv_init data err")); return (0); } } return (0); #if !defined(USE_UDP_ONLY) case TCP_PROTO: t = (tcp_Socket*) s; if (len > t->rdatalen) len = t->rdatalen; if (len) memcpy (buffer, r->recv_bufs, len); return (len); #endif } return (0); }
int sock_recv (udp_Socket *s, char *buffer, int len) { recv_buf *p; recv_data *r = (recv_data*) s->rdata; int i; if (r->recv_sig != RECV_USED) return (-1); switch (s->ip_type) { case UDP_PROTO: p = (recv_buf*) r->recv_bufs; /* find a used buffer */ for (i = 0; i < r->recv_bufnum; i++, p++) { switch (p->buf_sig) { case RECV_UNUSED: break; case RECV_USED: if (len > p->buf_len) len = p->buf_len; if (len > 0) memcpy (buffer, p->buf_data, len); p->buf_sig = RECV_UNUSED; return (len); default: outsnl (_LANG("ERROR: sock_recv_init data err")); return (0); } } return (0); #if !defined(USE_UDP_ONLY) case TCP_PROTO : { tcp_Socket *t = (tcp_Socket*) s; if (len > t->rdatalen) len = t->rdatalen; if (len) memcpy (buffer, r->recv_bufs, len); return (len); } #endif } return (0); }
static void icmp_print (int dbg_lvl, const char *msg, DWORD src) { if (debug_on < dbg_lvl) return; outs ("\nICMP: "); if (src) { outs ("("); outs (_inet_ntoa(NULL,intel(src))); outs ("): "); } outsnl (_LANG(msg)); }
/* * Do a reverse lookup on `my_ip_addr'. If successfull, replace * `hostname' and `def_domain' with returned result. */ int reverse_lookup_myip (void) { char myname [MAX_HOSTLEN]; if (!resolve_ip(htonl(my_ip_addr),myname)) return (0); if (debug_on >= 1) { outs (_LANG("My FQDN: ")); outsnl (myname); } if (sethostname(myname,sizeof(myname)) < 0) return (0); return (1); }
void ReadProtoFile (const char *fname) { static int been_here = 0; if (!fname || !*fname) return; if (been_here) /* loading multiple protocol files */ { free (protoFname); fclose (protoFile); protoFile = NULL; } been_here = 1; protoFname = strdup (fname); if (!protoFname) return; setprotoent (1); if (!protoFile) return; while (1) { struct _protoent *p, *p2 = (struct _protoent*) getprotoent(); if (!p2) break; p = malloc (sizeof(*p)); if (!p) { outsnl ("Protocol-file too big!\7"); break; } *p = *p2; p->next = _proto0; _proto0 = p; } rewind (protoFile); atexit (endprotoent); }
/* * _recvdaemon - gets upcalled when data arrives */ static int _recvdaemon (udp_Socket *s, BYTE *data, int len, tcp_PseudoHeader *ph, udp_Header *udp) { recv_data *r; recv_buf *p; int i; switch (s->ip_type) { case UDP_PROTO: r = (recv_data*)s->rdata; p = (recv_buf*) r->recv_bufs; if (r->recv_sig != RECV_USED) { outsnl (_LANG("ERROR: udp recv data conflict")); return (0); } /* find an unused buffer */ for (i = 0; i < r->recv_bufnum; i++, p++) switch (p->buf_sig) { case RECV_USED: break; case RECV_UNUSED: /* take this one */ p->buf_sig = RECV_USED; p->buf_hisip = ph->src; p->buf_hisport = udp->srcPort; len = min (len, sizeof(p->buf_data)); if (len > 0) { memcpy (p->buf_data, data, len); p->buf_len = len; } else p->buf_len = -1; /* a 0-byte probe */ return (0); default: outsnl (_LANG("ERROR: sock_recv_daemon data err")); return (0); } return (0); #if !defined(USE_UDP_ONLY) case TCP_PROTO: { tcp_Socket *t = (tcp_Socket*) s; r = (recv_data*) t->rdata; if (len > t->max_seg) return (0); if (r->recv_sig != RECV_USED) { outsnl (_LANG("ERROR: tcp recv data conflict")); return (0); } /* stick it on the end if you can */ i = t->maxrdatalen - t->rdatalen; if (i > 1) { /* we can accept some of this */ if (len > i) len = i; if (len > 0) memcpy (&r->recv_bufs[s->rdatalen], data, len); s->rdatalen += len; return (len); } return (0); /* didn't take none */ } #endif } return (0); }
/* * Open a TFTP connection on a random local port (our transaction ID). * Send the request, wait for first data block and send the first ACK. */ static int tftp_open (DWORD server, const char *fname) { int retry; WORD port = 69; #if defined(USE_BSD_API) struct servent *sp = getservbyname ("tftp", "udp"); if (sp) port = intel16 ((WORD)sp->s_port); #endif currblock = 0UL; blocksize = 0; for (retry = 0; retry < tftp_retry; retry++) { WORD our_tid; /* our transaction ID (local port) */ if (tftp_lport && tftp_lport < TFTP_PORT_LOW) outsnl (_LANG("tftp: Illegal local port.")); if (tftp_lport >= TFTP_PORT_LOW) our_tid = tftp_lport; else our_tid = Random (TFTP_PORT_LOW, TFTP_PORT_HIGH); /* Try to open a TFTP connection to the server */ if (!udp_open(&sock->udp, our_tid, server, port, NULL)) { TRACE (("tftp: %s\n", sockerr(sock))); return (0); } sock->udp.locflags |= LF_NOCLOSE; /* don't close socket on timeout */ /* Send the file request block, and then wait for the first data * block. If there is no response to the query, retry it with * another transaction ID (local port), so that all old packets get * discarded automatically. */ send_req (RRQ, fname); /* This hack makes it work because the response is sent back on * a source-port different from port 69; i.e. the server TID * uses a random port. Force the response packet to match a passive * socket in udp_handler(). */ sock->udp.hisaddr = 0; ibuflen = recv_packet (1); if (ibuflen >= 0) { blocksize = ibuflen; isopen = TRUE; send_ack (1); return (1); } /* If an error (except timeout) occurred, retries are useless */ if (tftp_errno == ERR_ERR || tftp_errno == ERR_UNKNOWN) break; } return (0); }
/** * Handler for incoming ICMP packets. */ void icmp_handler (const in_Header *ip, BOOL broadcast) { union ICMP_PKT *icmp; const in_Header *orig_ip; int type, code; unsigned len; DWORD delta_time; BOOL for_me, i_orig; /* is it for me, did I originate it */ const char *msg; DEBUG_RX (NULL, ip); if (block_icmp) /* application is handling ICMP; not needed */ return; len = in_GetHdrLen (ip); icmp = (union ICMP_PKT*) ((BYTE*)ip + len); len = intel16 (ip->length) - len; for_me = _ip4_is_multihome_addr (intel(ip->destination)); if (!for_me || broadcast) /* drop broadcast pings.. */ return; if (len < sizeof(icmp->info)) { STAT (icmpstats.icps_tooshort++); return; } if (CHECKSUM(icmp,len) != 0xFFFF) { STAT (icmpstats.icps_checksum++); icmp_print (1, _LANG("bad checksum"), ip->source); return; } type = icmp->unused.type; code = icmp->unused.code; orig_ip = &icmp->ip.ip; i_orig = _ip4_is_local_addr (intel(orig_ip->source)); if (type == ICMP_MASKREPLY) { if (!_do_mask_req) return; i_orig = TRUE; } /* !! this needs work */ if (!i_orig && (type != ICMP_ECHOREPLY && type != ICMP_ECHO && type != ICMP_IREQREPLY && type != ICMP_TSTAMP)) { icmp_bogus (ip, type, NULL); return; } switch (type) { case ICMP_ECHOREPLY: /* check if we were waiting for it */ delta_time = set_timeout(0) - icmp->echo.identifier; add_ping (intel(ip->source), delta_time, icmp->echo.index); return; case ICMP_UNREACH: if (code < DIM(icmp_unreach_str)) { UINT len_needed = 8 + in_GetHdrLen (orig_ip); WORD next_mtu = 0; msg = _LANG (icmp_unreach_str[code]); icmp_print (1, msg, ip->source); if (orig_ip->proto == TCP_PROTO || orig_ip->proto == UDP_PROTO) len_needed += 4; /* Need the src/dest port numbers */ if (len >= len_needed) { if (code == ICMP_UNREACH_NEEDFRAG) next_mtu = intel16 (icmp->needfrag.next_mtu); #if !defined(USE_UDP_ONLY) if (orig_ip->proto == TCP_PROTO) _tcp_cancel (orig_ip, ICMP_UNREACH, code, msg, &next_mtu); else #endif if (orig_ip->proto == UDP_PROTO) _udp_cancel (orig_ip, ICMP_UNREACH, code, msg, &next_mtu); /** \todo Handle cancelling raw sockets */ #if defined(USE_BSD_API) && 0 else _raw_cancel (orig_ip, ICMP_UNREACH, code, msg); #endif } else STAT (icmpstats.icps_tooshort++); } else STAT (icmpstats.icps_badcode++); return; case ICMP_SOURCEQUENCH: #if !defined(USE_UDP_ONLY) if (orig_ip->proto == TCP_PROTO) { msg = _LANG (icmp_type_str[type]); icmp_print (1, msg, ip->source); _tcp_cancel (orig_ip, ICMP_SOURCEQUENCH, code, msg, NULL); } #endif return; case ICMP_REDIRECT: if (code < DIM(icmp_redirect_str)) icmp_redirect (icmp, ip, orig_ip, code); else STAT (icmpstats.icps_badcode++); return; case ICMP_ECHO: icmp_print (2, _LANG("PING requested of us"), ip->source); icmp_echo_reply (ip, icmp, len); return; case ICMP_TIMXCEED: if (code >= DIM(icmp_exceed_str)) { STAT (icmpstats.icps_badcode++); return; } if (code == 0) /* "TTL exceeded in transit" */ switch (orig_ip->proto) { #if !defined(USE_UDP_ONLY) case TCP_PROTO: msg = _LANG (icmp_exceed_str[0]); icmp_print (1, msg, ip->source); _tcp_cancel (orig_ip, ICMP_TIMXCEED, code, msg, NULL); break; #endif case UDP_PROTO: msg = _LANG (icmp_exceed_str[0]); icmp_print (1, msg, ip->source); _udp_cancel (orig_ip, ICMP_TIMXCEED, code, msg, NULL); break; } return; case ICMP_PARAMPROB: msg = _LANG (icmp_type_str[ICMP_PARAMPROB]); switch (orig_ip->proto) { #if !defined(USE_UDP_ONLY) case TCP_PROTO: icmp_print (0, msg, ip->source); _tcp_cancel (orig_ip, ICMP_PARAMPROB, code, msg, NULL); break; #endif case UDP_PROTO: icmp_print (0, msg, ip->source); _udp_cancel (orig_ip, ICMP_PARAMPROB, code, msg, NULL); break; } return; case ICMP_ROUTERADVERT: /* todo !! */ msg = _LANG (icmp_type_str[ICMP_ROUTERADVERT]); icmp_print (1, msg, ip->source); return; case ICMP_ROUTERSOLICIT: /* todo !! */ msg = _LANG (icmp_type_str[ICMP_ROUTERSOLICIT]); icmp_print (1, msg, ip->source); return; case ICMP_TSTAMP: msg = _LANG (icmp_type_str[ICMP_TSTAMP]); icmp_print (1, msg, ip->source); /**< \todo send reply? */ return; case ICMP_TSTAMPREPLY: msg = _LANG (icmp_type_str[ICMP_TSTAMPREPLY]); icmp_print (1, msg, ip->source); /**< \todo should store */ return; case ICMP_IREQ: msg = _LANG (icmp_type_str[ICMP_IREQ]); icmp_print (1, msg, ip->source); /**< \todo send reply */ return; case ICMP_IREQREPLY: msg = _LANG (icmp_type_str[ICMP_IREQREPLY]); icmp_print (1, msg, ip->source); /**< \todo send reply upwards */ return; case ICMP_MASKREQ: /* might be sent by us, never answer */ break; case ICMP_MASKREPLY: msg = _LANG (icmp_type_str[ICMP_MASKREPLY]); icmp_print (0, msg, ip->source); if ((icmp->mask.identifier == addr_mask_id) && (icmp->mask.sequence == addr_mask_seq-1) && sin_mask != intel(icmp->mask.mask)) outsnl ("Conflicting net-mask from \"ICMP Addr Mask Reply\"\7"); addr_mask_id = 0; return; } }
/* * Gets upcalled when data arrives. * We MUST set 'p->buf_len = -1' to signal a 0-byte UDP packet * not 0 */ static int sock_recvdaemon (sock_type *s, const void *data, unsigned len, const tcp_PseudoHeader *ph, const udp_Header *udp) { recv_data *r; recv_buf *p; unsigned i; switch (s->udp.ip_type) { case UDP_PROTO: r = (recv_data*) s->udp.rx_data; p = (recv_buf*) r->recv_bufs; if (r->recv_sig != RECV_USED) { outsnl (_LANG("ERROR: udp recv data conflict")); return (0); } /* find an unused buffer */ for (i = 0; i < r->recv_bufnum; i++, p++) switch (p->buf_sig) { case RECV_USED: break; case RECV_UNUSED: /* take this one */ p->buf_sig = RECV_USED; p->buf_hisport = udp->srcPort; p->buf_seqnum = seq_num++; #if defined(USE_IPV6) if (s->udp.is_ip6) memcpy (&p->buf_hisip6, &((tcp_PseudoHeader6*)ph)->src, sizeof(p->buf_hisip6)); else #endif p->buf_hisip = ph->src; len = min (len, sizeof(p->buf_data)); if (len > 0) { memcpy (p->buf_data, data, len); p->buf_len = (short) len; } else p->buf_len = -1; /* a 0-byte probe */ #if 0 SOCK_DEBUGF (("\nsock_recvdaemon(): buffer %d, " "seq-num %ld, len %d", i, seq_num-1, p->buf_len)); #endif return (0); default: outsnl (_LANG("ERROR: sock_recv_daemon data err")); return (0); } return (0); #if !defined(USE_UDP_ONLY) case TCP_PROTO: { _tcp_Socket *t = &s->tcp; r = (recv_data*) t->rx_data; if (r->recv_sig != RECV_USED) { outsnl (_LANG("ERROR: tcp recv data conflict")); return (0); } /* stick it on the end if you can */ i = t->max_rx_data - t->rx_datalen; if (i > 1) { /* we can accept some of this */ if (len > i) len = i; if (len > 0) memcpy (r->recv_bufs + t->rx_datalen, data, len); t->rx_datalen += len; return (len); } return (0); /* didn't take none */ } #endif } return (0); }
/* * Load the BOOT-file from TFTP server */ int tftp_boot_load (void) { int rc = 0; /* Allocate socket and buffers */ sock = (sock_type*) malloc (sizeof(sock->udp)); inbuf = (struct tftphdr*) malloc (TFTP_HEADSIZE+SEGSIZE); outbuf = (struct tftphdr*) malloc (TFTP_HEADSIZE+SEGSIZE); if (!sock || !inbuf || !outbuf) { outsnl (_LANG("No memory for TFTP boot.")); return (0); } if (!tftp_boot_remote_file) { outsnl (_LANG("No remote TFTP boot filename defined.")); return (0); } if (tftp_server_name[0] && !tftp_server) tftp_server = resolve (tftp_server_name); if (!tftp_server) { outsnl (_LANG("Cannot resolve TFTP-server ")); return (0); } if (debug_on) outs (_LANG("Doing TFTP boot load...")); /* Open connection and request file */ if (!tftp_open (tftp_server, tftp_boot_remote_file)) { tftp_close(); return (0); } while (1) { const char *buf; int size = tftp_get_block (&buf); if (size < 0) /* error in transfer */ { rc = 0; break; } if (size > 0 && (*tftp_writer)(buf,size) < 0) { rc = -1; /* writer failed, errno set */ break; } if (size < blocksize) /* got last block */ { rc = 1; break; } } tftp_close(); return (rc); }
int sock_recv_from (sock_type *s, void *hisip, WORD *hisport, void *buffer, unsigned len, int peek) { #if !defined(USE_UDP_ONLY) _tcp_Socket *t; #endif recv_buf *p, *oldest = NULL; recv_data *r = (recv_data*) s->udp.rx_data; long seqnum = LONG_MAX; int i; if (r->recv_sig != RECV_USED) { SOCK_ERRNO (EBADF); /* To differentiate an error from 0-byte probe (also -1) */ return (-1); } switch (s->udp.ip_type) { case UDP_PROTO: p = (recv_buf*) r->recv_bufs; /* find the oldest used UDP buffer. */ for (i = 0; i < r->recv_bufnum; i++, p++) { switch (p->buf_sig) { case RECV_UNUSED: break; case RECV_USED: /* Drop looped packets sent by us (running * under Win32 DOS box using NDIS3PKT or SwsVpkt). */ if ((_eth_ndis3pkt || _eth_SwsVpkt) && !s->tcp.is_ip6 && p->buf_hisip == intel(my_ip_addr)) { p->buf_sig = RECV_UNUSED; continue; } if (p->buf_seqnum < seqnum) /* ignore wraps */ { seqnum = p->buf_seqnum; oldest = p; #if 0 SOCK_DEBUGF (("\nsock_recv_from(): buffer %d, " "seq-num %ld, len %d", i, seqnum, p->buf_len)); #endif } break; default: outsnl (_LANG("ERROR: sock_recv_init data err")); return (0); } } break; #if !defined(USE_UDP_ONLY) case TCP_PROTO: t = &s->tcp; len = min (len, (unsigned)t->rx_datalen); if (len) memcpy (buffer, r->recv_bufs, len); return (len); #endif } if (!oldest) return (0); /* found the oldest UDP packet */ p = oldest; if (p->buf_len < 0) /* a 0-byte probe packet */ len = -1; else { len = min ((unsigned)p->buf_len, len); memcpy (buffer, p->buf_data, len); } #if defined(USE_IPV6) if (s->tcp.is_ip6) { if (hisip) memcpy (hisip, &p->buf_hisip6, sizeof(ip6_address)); } else #endif if (hisip) *(DWORD*)hisip = p->buf_hisip; if (hisport) *hisport = p->buf_hisport; if (!peek) p->buf_sig = RECV_UNUSED; return (len); }
/** * Initialize the network driver interface. * \return 0 okay. * \return error-code otherwise. */ int _eth_init (void) { int rc; SIO_TRACE (("_eth_init")); if (_eth_is_init) return (0); rc = pkt_eth_init (&_eth_addr); if (rc) return (rc); /* error message already printed */ /* Save our MAC-address incase we change it. Change back at exit. */ memcpy (_eth_real_addr, _eth_addr, sizeof(_eth_real_addr)); switch (_pktdevclass) { case PDCLASS_ETHER: mac_tx_format = eth_mac_format; mac_transmit = eth_mac_xmit; break; case PDCLASS_TOKEN: case PDCLASS_TOKEN_RIF: mac_tx_format = tok_mac_format; mac_transmit = tok_mac_xmit; break; case PDCLASS_FDDI: mac_tx_format = fddi_mac_format; mac_transmit = fddi_mac_xmit; break; case PDCLASS_ARCNET: mac_tx_format = arcnet_mac_format; mac_transmit = arcnet_mac_xmit; break; case PDCLASS_SLIP: case PDCLASS_PPP: case PDCLASS_AX25: /* !! for now */ mac_tx_format = null_mac_format; mac_transmit = null_mac_xmit; break; default: outsnl (_LANG("No supported driver class found")); return (WERR_NO_DRIVER); } memset (TX_BUF(), 0, sizeof(union link_Packet)); memset (&_eth_brdcast, 0xFF, sizeof(_eth_brdcast)); _eth_loop_addr[0] = 0xCF; pkt_buf_wipe(); if (!_eth_get_hwtype(NULL, &_eth_mac_len)) _eth_mac_len = sizeof(eth_address); if (!strcmp(_pktdrvrname,"NDIS3PKT")) _eth_ndis3pkt = TRUE; else if (!strcmp(_pktdrvrname,"SwsVpkt")) _eth_SwsVpkt = TRUE; _eth_is_init = TRUE; RUNDOWN_ADD (_eth_release, 10); return (0); /* everything okay */ }
void ReadNetworksFile (const char *fname) { static BOOL been_here = FALSE; if (!fname || !*fname) return; if (been_here) /* loading multiple network files */ { free (networkFname); fclose (networkFile); networkFile = NULL; } networkFname = strdup (fname); if (!networkFname) return; setnetent (1); if (!networkFile) return; been_here = TRUE; while (1) { struct netent *n = getnetent(); struct _netent *n2; int i; if (!n) break; n2 = (struct _netent*) calloc (sizeof(*n2), 1); if (!n2) { outs (networkFname); outsnl (_LANG(" too big!")); break; } for (i = 0; n->n_aliases[i]; i++) n2->n_aliases[i] = strdup (n->n_aliases[i]); n2->n_net = n->n_net; n2->n_addrtype = n->n_addrtype; n2->n_name = strdup (n->n_name); if (!n2->n_name) break; n2->n_next = network0; network0 = n2; } rewind (networkFile); RUNDOWN_ADD (endnetent, 251); #if 0 /* test */ { struct _netent *n; printf ("\n%s entries:\n", networkFname); for (n = network0; n; n = n->n_next) { int i; printf ("net %-15.15s name %-10.10s Aliases:", inet_ntoa(inet_makeaddr(n->n_net,0)), n->n_name); for (i = 0; n->n_aliases[i]; i++) printf (" %s,", n->n_aliases[i]); puts (""); } fflush (stdout); } #endif }
/* * Handler for incoming ICMP packets */ void icmp_handler (const in_Header *ip, BOOL broadcast) { union icmp_pkt *icmp; in_Header *orig_ip; int len, type, code; BOOL for_me, i_orig; /* is it for me, did I originate it */ const char *msg; DEBUG_RX (NULL, ip); if (block_icmp) /* application is handling ICMP; not needed */ return; len = in_GetHdrLen (ip); icmp = (union icmp_pkt*) ((BYTE*)ip + len); len = intel16 (ip->length) - len; for_me = (DWORD) (intel(ip->destination) - my_ip_addr) <= multihomes; if (!for_me || broadcast) /* drop broadcast pings.. */ return; if (len < sizeof(icmp->info)) { STAT (icmpstats.icps_tooshort++); return; } if (checksum(icmp,len) != 0xFFFF) { STAT (icmpstats.icps_checksum++); icmp_print (1, _LANG("bad checksum"), ip->source); return; } type = icmp->unused.type; code = icmp->unused.code; orig_ip = &icmp->ip.ip; i_orig = is_local_addr (intel(orig_ip->source)); if (type == ICMP_MASKREPLY) { if (!_domask_req) return; i_orig = TRUE; } /* !! this needs work */ if (!i_orig && (type != ICMP_ECHOREPLY && type != ICMP_ECHO && type != ICMP_IREQREPLY && type != ICMP_TSTAMP)) { icmp_bogus (ip, type, NULL); return; } switch (type) { case ICMP_ECHOREPLY: /* check if we were waiting for it */ STAT (icmpstats.icps_inhist[ICMP_ECHOREPLY]++); ping_hcache = intel (ip->source); ping_tcache = set_timeout (1000) - *(DWORD*)&icmp->echo.identifier; if (ping_tcache > 0x7FFFFFFFL) ping_tcache += 0x1800B0L; ping_number = *(DWORD*)(((BYTE*)&icmp->echo.identifier) + 4); return; case ICMP_UNREACH: STAT (icmpstats.icps_inhist[ICMP_UNREACH]++); if (code < DIM(icmp_unreach_str)) { icmp_print (1, msg = icmp_unreach_str[code], ip->source); #if !defined(USE_UDP_ONLY) if (orig_ip->proto == TCP_PROTO) _tcp_cancel (orig_ip, type, msg, 0); else #endif if (orig_ip->proto == UDP_PROTO) _udp_cancel (orig_ip, type, msg, 0); } else STAT (icmpstats.icps_badcode++); return; case ICMP_SOURCEQUENCH: STAT (icmpstats.icps_inhist[ICMP_SOURCEQUENCH]++); #if !defined(USE_UDP_ONLY) if (orig_ip->proto == TCP_PROTO) { icmp_print (1, _LANG("Source Quench"), ip->source); _tcp_cancel (orig_ip, type, NULL, 0); } #endif return; case ICMP_REDIRECT: STAT (icmpstats.icps_inhist[ICMP_REDIRECT]++); if (code < 4) { DWORD new_gw = intel (icmp->ip.ipaddr); /* Check if new gateway is on our subnet */ if ((new_gw ^ my_ip_addr) & sin_mask) { char buf[100], adr[20]; strcpy (buf, ", GW = "); strcat (buf, _inet_ntoa(adr,new_gw)); icmp_bogus (ip, type, buf); return; } icmp_print (1, msg = icmp_redirect_str[code], ip->source); switch (orig_ip->proto) { #if !defined(USE_UDP_ONLY) case TCP_PROTO: if (do_redirect.tcp) /* do it to some socket */ _tcp_cancel (orig_ip, type, msg, new_gw); break; #endif case UDP_PROTO: if (do_redirect.udp) _udp_cancel (orig_ip, type, msg, new_gw); break; case ICMP_PROTO: if (do_redirect.icmp) { _ip_recursion = 1; _arp_register (new_gw, intel(orig_ip->destination), 0); _ip_recursion = 0; } break; case IGMP_PROTO: if (do_redirect.igmp) { _ip_recursion = 1; _arp_register (new_gw, intel(orig_ip->destination), 0); _ip_recursion = 0; } break; } } else STAT (icmpstats.icps_badcode++); return; case ICMP_ECHO: STAT (icmpstats.icps_inhist[ICMP_ECHO]++); icmp_print (2, _LANG("PING requested of us"), ip->source); { /* Extract eth-address and create Echo reply packet. */ struct _pkt *pkt; union icmp_pkt *newicmp; if (!icmp_chk_src(ip,ICMP_ECHO)) return; pkt = (struct _pkt*) _eth_formatpacket (MAC_SRC(ip), IP_TYPE); newicmp = &pkt->icmp; /* Don't let a huge reassembled ICMP-packet kill us. */ len = min (len, mtu - sizeof(*ip)); memcpy (newicmp, icmp, len); newicmp->echo.type = ICMP_ECHOREPLY; newicmp->echo.code = code; /* Use supplied ip values in case we ever multi-home. * Note that ip values are still in network order. */ icmp_send (pkt, ip->destination, ip->source, len); icmp_print (2, _LANG("PING reply sent"), 0); } return; case ICMP_TIMXCEED: if (code >= DIM(icmp_exceed_str)) { STAT (icmpstats.icps_badcode++); return; } STAT (icmpstats.icps_inhist[ICMP_TIMXCEED]++); if (code != 1) switch (orig_ip->proto) { #if !defined(USE_UDP_ONLY) case TCP_PROTO: icmp_print (1, icmp_exceed_str[code], ip->source); _tcp_cancel (orig_ip, ICMP_TIMXCEED, NULL, 0); break; #endif case UDP_PROTO: icmp_print (1, icmp_exceed_str[code], ip->source); _udp_cancel (orig_ip, ICMP_TIMXCEED, NULL, 0); break; } return; case ICMP_PARAMPROB: STAT (icmpstats.icps_inhist[ICMP_PARAMPROB]++); switch (orig_ip->proto) { #if !defined(USE_UDP_ONLY) case TCP_PROTO: icmp_print (0, _LANG(icmp_type_str[type]), ip->source); _tcp_cancel (orig_ip, type, NULL, 0); break; #endif case UDP_PROTO: icmp_print (0, _LANG(icmp_type_str[type]), ip->source); _udp_cancel (orig_ip, type, NULL, 0); break; } return; case ICMP_ROUTERADVERT: /* todo !! */ STAT (icmpstats.icps_inhist[ICMP_ROUTERADVERT]++); icmp_print (1, _LANG(icmp_type_str[type]), ip->source); return; case ICMP_ROUTERSOLICIT: /* todo !! */ STAT (icmpstats.icps_inhist[ICMP_ROUTERSOLICIT]++); icmp_print (1, _LANG(icmp_type_str[type]), ip->source); return; case ICMP_TSTAMP: STAT (icmpstats.icps_inhist[ICMP_TSTAMP]++); icmp_print (1, _LANG(icmp_type_str[type]), ip->source); /* todo!!, send reply? */ return; case ICMP_TSTAMPREPLY: STAT (icmpstats.icps_inhist[ICMP_TSTAMPREPLY]++); icmp_print (1, _LANG(icmp_type_str[type]), ip->source); /* todo!!, should store */ return; case ICMP_IREQ: STAT (icmpstats.icps_inhist[ICMP_IREQ]++); icmp_print (1, _LANG(icmp_type_str[type]), ip->source); /* todo!!, send reply */ return; case ICMP_IREQREPLY: STAT (icmpstats.icps_inhist[ICMP_IREQREPLY]++); icmp_print (1, _LANG(icmp_type_str[type]), ip->source); /* todo!!, send reply upwards */ return; case ICMP_MASKREQ: STAT (icmpstats.icps_inhist[ICMP_MASKREQ]++); break; case ICMP_MASKREPLY: STAT (icmpstats.icps_inhist[ICMP_MASKREPLY]++); icmp_print (0, _LANG(icmp_type_str[type]), ip->source); if ((icmp->mask.identifier == addr_mask_id) && (icmp->mask.sequence == addr_mask_seq-1) && sin_mask != intel(icmp->mask.mask)) outsnl ("Conflicting net-mask from \"ICMP Addr Mask Reply\"\7"); addr_mask_id = 0; return; } }
void backgroundon (void) { outsnl (_LANG("Use wintr_init() / wintr_enable() instead")); exit (3); }
void ReadHostsFile (const char *fname) { static BOOL been_here = FALSE; if (!fname || !*fname) return; if (been_here) /* loading multiple hosts files */ { free (hostFname); fclose (hostFile); hostFile = NULL; } hostFname = strdup (fname); if (!hostFname) return; sethostent (1); if (!hostFile) return; been_here = TRUE; while (1) { struct hostent *h = gethostent(); struct _hostent *h2; int i; if (!h) break; h2 = (struct _hostent*) calloc (sizeof(*h2), 1); if (!h2) { outs (hostFname); outsnl (_LANG(" too big!")); break; } for (i = 0; h->h_aliases[i]; i++) h2->h_aliases[i] = strdup (h->h_aliases[i]); h2->h_name = strdup (h->h_name); h2->h_address[0] = *(DWORD*) h->h_addr_list[0]; h2->h_num_addr = 1; if (!h2->h_name) break; h2->h_next = host0; host0 = h2; } #if 0 /* test !! */ { const struct _hostent *h; int i; printf ("\n%s entries:\n", hostFname); for (h = host0; h; h = h->h_next) { printf ("address = %-17.17s name = %-30.30s Aliases:", inet_ntoa(*(struct in_addr*)&h->h_address[0]), h->h_name); for (i = 0; h->h_aliases[i]; i++) printf (" %s,", h->h_aliases[i]); puts (""); } fflush (stdout); } #endif rewind (hostFile); RUNDOWN_ADD (endhostent, 254); }
/* * Warn about calling 'getXbyY()' functions before calling * 'watt_sock_init()'. Many other functions will fail if we're not * initialised, but 'getXbyY()' are often used during application * startup. */ void uninit_warn (const char *func) { outs ("Warning: function \""); outs (func); outsnl ("()\" called before \"sock_init()\"."); }
/* * Unhook signal-handlers and optionally chain to previous handlers * if we caught signals. */ void _sock_sig_restore (void) { if (signal_depth == 0) return; if (--signal_depth > 0) return; _sock_stop_timer(); watcbroke = 0; wathndlcbrk = wat_brkmode; #if defined(SIGALRM) && TRAP_SIGALRM signal (SIGALRM, old_sigalrm); unblock_sigalrm(); #if 0 /* don't do this since a socket function might be called from an * alarm handler. This could cause serious recursion and stack fault. */ if (sigalrm_caught && old_sigalrm != SIG_IGN && old_sigalrm != SIG_DFL) { sigalrm_caught = 0; (*old_sigalrm) (SIGALRM); } #endif #endif #if defined(SIGBREAK) signal (SIGBREAK, old_sigbrk); if (sigbrk_caught && old_sigbrk != SIG_IGN && old_sigbrk != SIG_DFL) { sigbrk_caught = 0; (*old_sigbrk) (SIGBREAK); } #endif #if defined(SIGPIPE) signal (SIGPIPE, old_sigpipe); if (sigpipe_caught) { if (old_sigpipe != SIG_IGN && old_sigpipe != SIG_DFL) { sigpipe_caught = 0; (*old_sigpipe) (SIGPIPE); } else { outsnl (_LANG("Terminating on SIGPIPE")); exit (-1); } } #endif #if defined(SIGQUIT) signal (SIGQUIT, old_sigquit); if (sigquit_caught) { if (old_sigquit != SIG_IGN && old_sigquit != SIG_DFL) { sigquit_caught = 0; (*old_sigquit) (SIGQUIT); } else { SOCK_DEBUGF ((NULL, "\nExiting stuck program")); exit (-1); } } #endif signal (SIGINT, old_sigint); if (sigint_caught && old_sigint != SIG_IGN && old_sigint != SIG_DFL) { sigint_caught = 0; (*old_sigint) (SIGINT); } sigalrm_caught = sigbrk_caught = 0; sigint_caught = sigquit_caught = 0; sigpipe_caught = 0; }
/* * ___trace2com() - Strings passed here are dumped to the set-up serial * "com" port. If the string is < 16 chars long, it will fit into the * 16550 UARTs FIFO and will not cause any significant delay. * No interrupts are used, so this will not interfere with anything * else that might be happening. */ int MS_CDECL __trace2com (const char *fmt, ...) { int fifoLeft = 0; /* Assume TX FIFO is full on first round -> force check */ char buf [256]; int len, i; va_list args; if (trace2com_base <= 0) /* Not yet initialized */ return (0); va_start (args, fmt); #if defined(VSNPRINTF) len = VSNPRINTF (buf, sizeof(buf)-1, fmt, args); if (len < 0 || len >= SIZEOF(buf)-1) { outsnl (_LANG("ERROR: __trace2com() overrun")); len = sizeof(buf)-1; buf [len] = '\0'; } #else len = vsprintf (buf, fmt, args); if (len > SIZEOF(buf)) /* harm already done, but better than no test */ { outsnl (_LANG("ERROR: __trace2com() overrun")); return (0); } #endif for (i = 0; i < len; i++) { DWORD to = set_timeout (400000/trace2com_speed); /* 10ms at 38kB/s */ if (--fifoLeft < 0) /* Is the TX FIFO full? */ { /* Wait until THRE or TX FIFO empty */ while (!(_inportb (trace2com_base+LSR_REG) & LSR_THRE)) { if (chk_timeout(to)) return (i); } fifoLeft = trace2com_fifoSize_1; /* Now we can fill it up again */ } _outportb (trace2com_base+TXRX_REG, buf[i]); } if (--fifoLeft < 0) { DWORD to = set_timeout (400000/trace2com_speed); /* Wait until THRE or TX FIFO empty */ while (!(_inportb (trace2com_base+LSR_REG) & LSR_THRE)) { if (chk_timeout(to)) return (len); } } _outportb (trace2com_base+TXRX_REG, '\r'); _outportb (trace2com_base+TXRX_REG, '\n'); return (len+2); }