/** * Build and send a PPPoE Session packet (IPCP or LCP packet). */ int pppoe_send_sess (const void *sock, const BYTE *buf, WORD len) { pppoe_Packet *pkt; pkt = (pppoe_Packet*) _eth_formatpacket (&ac_macAddr[0], PPPOE_SESS_TYPE); pkt->ver = 1; pkt->type = 1; pkt->code = PPPOE_CODE_SESS; pkt->session = session; pkt->length = intel16 (len); memcpy (pkt->data, buf, len); return _eth_send (len + PPPOE_HDR_SIZE, sock, __FILE__, __LINE__); }
static int _rarp_request (void) { rarp_Header *rarp = (rarp_Header*) _eth_formatpacket (&_eth_brdcast[0], RARP_TYPE); rarp->hwType = intel16 (_eth_get_hwtype(NULL,NULL)); rarp->protType = IP4_TYPE; rarp->hwAddrLen = sizeof (mac_address); rarp->protoAddrLen = sizeof (my_ip_addr); rarp->opcode = RARP_REQUEST; rarp->srcIPAddr = 0; rarp->dstIPAddr = 0; memcpy (rarp->srcEthAddr, _eth_addr, sizeof(mac_address)); memcpy (rarp->dstEthAddr, _eth_addr, sizeof(mac_address)); return _eth_send (sizeof(*rarp), NULL, __FILE__, __LINE__); }
/** * Build and send a PADx (PPPoE Active Discovery) packet as * link-layer broadcast or unicast. */ static int pppoe_send_disc (int code) { pppoe_Packet *pkt; WORD len; pkt = (pppoe_Packet*) _eth_formatpacket (&ac_macAddr[0], PPPOE_DISC_TYPE); len = build_pad (pkt, code); pkt->ver = 1; pkt->type = 1; pkt->code = code; pkt->session = session; pkt->length = intel16 (len); #if defined(USE_DEBUG) if (cfg.trace) (*_printf) ("PPPOE: sending %s\n", pppoe_get_code(code)); #endif return _eth_send (len + PPPOE_HDR_SIZE, NULL, __FILE__, __LINE__); }
/* * Raw IP transmitter */ static int ip_transmit (Socket *socket, const void *tx, int len) { eth_address eth; u_long dest; unsigned tx_len, tx_room; sock_type *sk = (sock_type*)socket->udp_sock; struct ip *ip = (struct ip*) tx; const BYTE *buf = (const BYTE*) tx; WORD flags = 0; DWORD offset; UINT h_len, o_len; tcp_tick (NULL); /* process other TCBs too */ tcp_Retransmitter (1); /* This should never happen */ if (ip && (socket->so_state & SS_NBIO) && sock_tbleft(sk) < (len + socket->send_lowat)) { SOCK_DEBUGF ((socket, ", EWOULDBLOCK")); SOCK_ERR (EWOULDBLOCK); return (-1); } if (ip) { offset = ntohs (ip->ip_off); flags = offset & ~IP_OFFMASK; offset = (offset & IP_OFFMASK) << 3; /* 0 <= ip_ofs <= 65536-8 */ } SOCK_DEBUGF ((socket, ", %s / Raw", inet_ntoa(socket->remote_addr->sin_addr))); if (ip && (socket->inp_flags & INP_HDRINCL)) { dest = ip->ip_dst.s_addr; tx_len = len; tx_room = mtu; } else { dest = socket->remote_addr->sin_addr.s_addr; tx_len = len + sizeof (*ip); tx_room = mtu + sizeof (*ip); } if (!dest || !_arp_resolve(ntohl(dest),ð,0)) { SOCK_DEBUGF ((socket, ", no route")); SOCK_ERR (EHOSTUNREACH); STAT (ipstats.ips_noroute++); return (-1); } #if defined(USE_FRAGMENTS) if (!(socket->inp_flags & INP_HDRINCL) && tx_len + socket->ip_opt_len > tx_room) { sk = (sock_type*)socket->raw_sock; if (flags & IP_DF) { SOCK_DEBUGF ((socket, ", EMSGSIZE")); SOCK_ERR (EMSGSIZE); STAT (ipstats.ips_toolong++); return (-1); } return SEND_IP_FRAGMENTS (sk, sk->raw.ip_type, dest, buf, len); } #else if (!(socket->inp_flags & INP_HDRINCL) && tx_len + socket->ip_opt_len > tx_room) { SOCK_DEBUGF ((socket, ", EMSGSIZE")); SOCK_ERR (EMSGSIZE); STAT (ipstats.ips_toolong++); return (-1); } #endif ip = (struct ip*) _eth_formatpacket (ð, IP_TYPE); if (socket->inp_flags & INP_HDRINCL) { memcpy (ip, buf, len); if (ip->ip_src.s_addr == 0) { ip->ip_src.s_addr = gethostid(); ip->ip_sum = 0; ip->ip_sum = ~checksum ((void*)ip, ip->ip_hl << 2); } if (ip->ip_sum == 0) ip->ip_sum = ~checksum ((void*)ip, ip->ip_hl << 2); } else { if (socket->ip_opt && socket->ip_opt_len > 0) { BYTE *data; o_len = min (socket->ip_opt_len, sizeof(socket->ip_opt->ip_opts)); h_len = sizeof(*ip) + o_len; data = (BYTE*)ip + h_len; memcpy (ip+1, &socket->ip_opt->ip_opts, o_len); memcpy (data, buf, len); tx_len += o_len; if (socket->ip_opt->ip_dst.s_addr) /* using source routing */ dest = socket->ip_opt->ip_dst.s_addr; } else { if (buf) memcpy (ip+1, buf, len); h_len = sizeof (*ip); } ip->ip_v = IPVERSION; ip->ip_hl = h_len >> 2; ip->ip_tos = socket->ip_tos; ip->ip_len = htons (tx_len); ip->ip_id = _get_ip_id(); ip->ip_off = 0; ip->ip_ttl = socket->ip_ttl; ip->ip_p = socket->so_proto; ip->ip_src.s_addr = gethostid(); ip->ip_dst.s_addr = dest; ip->ip_sum = 0; ip->ip_sum = ~checksum (ip, h_len); } DEBUG_TX (NULL, ip); if (!_eth_send(tx_len)) { SOCK_DEBUGF ((socket, ", ENETDOWN")); SOCK_ERR (ENETDOWN); return (-1); } if (buf) buf += tx_len; return (len); }