static int LibAliasOutLocked(struct libalias *la, char *ptr, /* valid IP packet */ int maxpacketsize, /* How much the packet data may grow (FTP * and IRC inline changes) */ int create /* Create new entries ? */ ) { int iresult; struct in_addr addr_save; struct ip *pip; if (la->packetAliasMode & PKT_ALIAS_REVERSE) { la->packetAliasMode &= ~PKT_ALIAS_REVERSE; iresult = LibAliasInLocked(la, ptr, maxpacketsize); la->packetAliasMode |= PKT_ALIAS_REVERSE; goto getout; } HouseKeeping(la); ClearCheckNewLink(la); pip = (struct ip *)ptr; /* Defense against mangled packets */ if (ntohs(pip->ip_len) > maxpacketsize || (pip->ip_hl << 2) > maxpacketsize) { iresult = PKT_ALIAS_IGNORED; goto getout; } addr_save = GetDefaultAliasAddress(la); if (la->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(la, pip->ip_src); } } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) { SetDefaultAliasAddress(la, pip->ip_src); } iresult = PKT_ALIAS_IGNORED; if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { switch (pip->ip_p) { case IPPROTO_ICMP: iresult = IcmpAliasOut(la, pip, create); break; case IPPROTO_UDP: iresult = UdpAliasOut(la, pip, maxpacketsize, create); break; case IPPROTO_TCP: iresult = TcpAliasOut(la, pip, maxpacketsize, create); break; #ifdef _KERNEL case IPPROTO_SCTP: iresult = SctpAlias(la, pip, SN_TO_GLOBAL); break; #endif case IPPROTO_GRE: { int error; struct alias_data ad = { .lnk = NULL, .oaddr = NULL, .aaddr = NULL, .aport = NULL, .sport = NULL, .dport = NULL, .maxpktsize = 0 }; /* Walk out chain. */ error = find_handler(OUT, IP, la, pip, &ad); if (error == 0) iresult = PKT_ALIAS_OK; else iresult = ProtoAliasOut(la, &pip->ip_src, pip->ip_dst, pip->ip_p, &pip->ip_sum, create); } break; default: iresult = ProtoAliasOut(la, &pip->ip_src, pip->ip_dst, pip->ip_p, &pip->ip_sum, create); break; } } else { iresult = FragmentOut(la, &pip->ip_src, &pip->ip_sum); } SetDefaultAliasAddress(la, addr_save); getout: return (iresult); }
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); }