-/* Do packet manipulations according to binding. */
-unsigned int
-do_bindings(struct ip_conntrack *ct,
- enum ip_conntrack_info ctinfo,
- struct ip_nat_info *info,
- unsigned int hooknum,
- struct sk_buff **pskb)
-{
- unsigned int i;
- struct ip_nat_helper *helper;
- enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
- int proto = (*pskb)->nh.iph->protocol;
-
- /* Need nat lock to protect against modification, but neither
- conntrack (referenced) and helper (deleted with
- synchronize_bh()) can vanish. */
- READ_LOCK(&ip_nat_lock);
- for (i = 0; i < info->num_manips; i++) {
- if (info->manips[i].direction == dir
- && info->manips[i].hooknum == hooknum) {
- DEBUGP("Mangling %p: %s to %u.%u.%u.%u %u\n",
- *pskb,
- info->manips[i].maniptype == IP_NAT_MANIP_SRC
- ? "SRC" : "DST",
- NIPQUAD(info->manips[i].manip.ip),
- htons(info->manips[i].manip.u.all));
- if (!manip_pkt(proto, pskb, 0,
- &info->manips[i].manip,
- info->manips[i].maniptype)) {
- READ_UNLOCK(&ip_nat_lock);
- return NF_DROP;
- }
- }
- }
- helper = info->helper;
- READ_UNLOCK(&ip_nat_lock);
-
- if (helper) {
- struct ip_conntrack_expect *exp = NULL;
- struct list_head *cur_item;
- int ret = NF_ACCEPT;
- int helper_called = 0;
-
- DEBUGP("do_bindings: helper existing for (%p)\n", ct);
-
- /* Always defragged for helpers */
- IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off
- & htons(IP_MF|IP_OFFSET)));
-
- /* Have to grab read lock before sibling_list traversal */
- READ_LOCK(&ip_conntrack_lock);
- list_for_each_prev(cur_item, &ct->sibling_list) {
- exp = list_entry(cur_item, struct ip_conntrack_expect,
- expected_list);
-
- /* if this expectation is already established, skip */
- if (exp->sibling)
- continue;
-
- if (exp_for_packet(exp, *pskb)) {
- /* FIXME: May be true multiple times in the
- * case of UDP!! */
- DEBUGP("calling nat helper (exp=%p) for packet\n", exp);
- ret = helper->help(ct, exp, info, ctinfo,
- hooknum, pskb);
- if (ret != NF_ACCEPT) {
- READ_UNLOCK(&ip_conntrack_lock);
- return ret;
- }
- helper_called = 1;
- }
- }
- /* Helper might want to manip the packet even when there is no
- * matching expectation for this packet */
- if (!helper_called && helper->flags & IP_NAT_HELPER_F_ALWAYS) {
- DEBUGP("calling nat helper for packet without expectation\n");
- ret = helper->help(ct, NULL, info, ctinfo,
- hooknum, pskb);
- if (ret != NF_ACCEPT) {
- READ_UNLOCK(&ip_conntrack_lock);
- return ret;
- }
- }
- READ_UNLOCK(&ip_conntrack_lock);
-
- /* Adjust sequence number only once per packet
- * (helper is called at all hooks) */
- if (proto == IPPROTO_TCP
- && (hooknum == NF_IP_POST_ROUTING
- || hooknum == NF_IP_LOCAL_IN)) {
- DEBUGP("ip_nat_core: adjusting sequence number\n");
- /* future: put this in a l4-proto specific function,
- * and call this function here. */
- if (!ip_nat_seq_adjust(pskb, ct, ctinfo))
- ret = NF_DROP;
- }