int PacketAliasOut(char *ptr, /* valid IP packet */ int maxpacketsize /* How much the packet data may grow (FTP and IRC inline changes) */ ) { int iresult; struct in_addr addr_save; struct ip *pip; if (packetAliasMode & PKT_ALIAS_REVERSE) { packetAliasMode &= ~PKT_ALIAS_REVERSE; iresult = PacketAliasIn(ptr, maxpacketsize); packetAliasMode |= PKT_ALIAS_REVERSE; return iresult; } HouseKeeping(); ClearCheckNewLink(); pip = (struct ip *) ptr; /* Defense against mangled packets */ if (ntohs(pip->ip_len) > maxpacketsize || (pip->ip_hl<<2) > maxpacketsize) return PKT_ALIAS_IGNORED; addr_save = GetDefaultAliasAddress(); if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) { u_long addr; int iclass; iclass = 0; addr = ntohl(pip->ip_src.s_addr); if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) iclass = 3; else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) iclass = 2; else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) iclass = 1; if (iclass == 0) { SetDefaultAliasAddress(pip->ip_src); } } iresult = PKT_ALIAS_IGNORED; if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { switch (pip->ip_p) { case IPPROTO_ICMP: iresult = IcmpAliasOut(pip); break; case IPPROTO_UDP: iresult = UdpAliasOut(pip); break; case IPPROTO_TCP: iresult = TcpAliasOut(pip, maxpacketsize); break; case IPPROTO_GRE: if (AliasHandlePptpGreOut(pip) == 0) iresult = PKT_ALIAS_OK; else iresult = ProtoAliasOut(pip); break; default: iresult = ProtoAliasOut(pip); break; } } else { iresult = FragmentOut(pip); } SetDefaultAliasAddress(addr_save); return(iresult); }
static void DoAliasing (int fd, int direction) { int bytes; int origBytes; int status; int addrSize; struct ip* ip; if (assignAliasAddr) { SetAliasAddressFromIfName (ifName); assignAliasAddr = 0; } /* * Get packet from socket. */ addrSize = sizeof packetAddr; origBytes = recvfrom (fd, packetBuf, sizeof packetBuf, 0, (struct sockaddr*) &packetAddr, &addrSize); if (origBytes == -1) { if (errno != EINTR) Warn ("read from divert socket failed"); return; } /* * This is a IP packet. */ ip = (struct ip*) packetBuf; if (direction == DONT_KNOW) { if (packetAddr.sin_addr.s_addr == INADDR_ANY) direction = OUTPUT; else direction = INPUT; } if (verbose) { /* * Print packet direction and protocol type. */ printf (direction == OUTPUT ? "Out " : "In "); switch (ip->ip_p) { case IPPROTO_TCP: printf ("[TCP] "); break; case IPPROTO_UDP: printf ("[UDP] "); break; case IPPROTO_ICMP: printf ("[ICMP] "); break; default: printf ("[%d] ", ip->ip_p); break; } /* * Print addresses. */ PrintPacket (ip); } if (direction == OUTPUT) { /* * Outgoing packets. Do aliasing. */ PacketAliasOut (packetBuf, IP_MAXPACKET); } else { /* * Do aliasing. */ status = PacketAliasIn (packetBuf, IP_MAXPACKET); if (status == PKT_ALIAS_IGNORED && dropIgnoredIncoming) { if (verbose) printf (" dropped.\n"); if (logDropped) SyslogPacket (ip, LOG_WARNING, "denied"); return; } } /* * Length might have changed during aliasing. */ bytes = ntohs (ip->ip_len); /* * Update alias overhead size for outgoing packets. */ if (direction == OUTPUT && bytes - origBytes > aliasOverhead) aliasOverhead = bytes - origBytes; if (verbose) { /* * Print addresses after aliasing. */ printf (" aliased to\n"); printf (" "); PrintPacket (ip); printf ("\n"); } packetLen = bytes; packetSock = fd; packetDirection = direction; FlushPacketBuffer (fd); }
static void DoAliasing(int fd, int direction) { int bytes; int origBytes; char buf[IP_MAXPACKET]; struct sockaddr_in addr; int wrote; int status; int addrSize; struct ip* ip; char msgBuf[80]; if (assignAliasAddr) { SetAliasAddressFromIfName(ifName); assignAliasAddr = 0; } /* * Get packet from socket. */ addrSize = sizeof addr; origBytes = recvfrom(fd, buf, sizeof buf, 0, (struct sockaddr *)&addr, &addrSize); if (origBytes == -1) { if (errno != EINTR) Warn("read from divert socket failed"); return; } /* * This is a IP packet. */ ip = (struct ip *)buf; if (direction == DONT_KNOW) { if (addr.sin_addr.s_addr == INADDR_ANY) direction = OUTPUT; else direction = INPUT; } if (verbose) { /* * Print packet direction and protocol type. */ printf(direction == OUTPUT ? "Out " : "In "); switch (ip->ip_p) { case IPPROTO_TCP: printf("[TCP] "); break; case IPPROTO_UDP: printf("[UDP] "); break; case IPPROTO_ICMP: printf("[ICMP] "); break; default: printf("[%d] ", ip->ip_p); break; } /* * Print addresses. */ PrintPacket(ip); } if (direction == OUTPUT) { /* * Outgoing packets. Do aliasing. */ PacketAliasOut(buf, IP_MAXPACKET); } else { /* * Do aliasing. */ status = PacketAliasIn(buf, IP_MAXPACKET); if (status == PKT_ALIAS_IGNORED && dropIgnoredIncoming) { if (verbose) printf(" dropped.\n"); if (logDropped) SyslogPacket(ip, LOG_WARNING, "denied"); return; } } /* * Length might have changed during aliasing. */ bytes = ntohs(ip->ip_len); /* * Update alias overhead size for outgoing packets. */ if (direction == OUTPUT && bytes - origBytes > aliasOverhead) aliasOverhead = bytes - origBytes; if (verbose) { /* * Print addresses after aliasing. */ printf(" aliased to\n"); printf(" "); PrintPacket(ip); printf("\n"); } /* * Put packet back for processing. */ wrote = sendto(fd, buf, bytes, 0, (struct sockaddr *)&addr, sizeof addr); if (wrote != bytes) { if (errno == EMSGSIZE) { if (direction == OUTPUT && ifMTU != -1) SendNeedFragIcmp(icmpSock, (struct ip *)buf, ifMTU - aliasOverhead); } else if (errno == EACCES && logIpfwDenied) { sprintf(msgBuf, "failed to write packet back"); Warn(msgBuf); } } }