void basic_socket_impl::switch_to_create_thread(stream_buffer dat, bool close_this, bool sync) { if (sync) { send_data(dat); } else { add_to_send_queue(dat, close_this); } }
void ip_queue_xmit(struct sock *sk, struct device *dev, struct sk_buff *skb, int free) { unsigned int tot_len; struct iphdr *iph; IS_SKB(skb); /* * Do some book-keeping in the packet for later */ skb->sk = sk; skb->dev = dev; skb->when = jiffies; /* * Find the IP header and set the length. This is bad * but once we get the skb data handling code in the * hardware will push its header sensibly and we will * set skb->ip_hdr to avoid this mess and the fixed * header length problem */ iph = skb->ip_hdr; tot_len = skb->len - (((unsigned char *)iph) - skb->data); iph->tot_len = htons(tot_len); switch (free) { /* No reassigning numbers to fragments... */ default: free = 1; break; case 0: add_to_send_queue(sk, skb); /* fall through */ case 1: iph->id = htons(ip_id_count++); } skb->free = free; /* Sanity check */ if (dev == NULL) goto no_device; #ifdef CONFIG_FIREWALL if (call_out_firewall(PF_INET, skb->dev, iph, NULL) < FW_ACCEPT) goto out; #endif /* * Do we need to fragment. Again this is inefficient. * We need to somehow lock the original buffer and use * bits of it. */ if (tot_len > dev->mtu) goto fragment; /* * Add an IP checksum */ ip_send_check(iph); /* * More debugging. You cannot queue a packet already on a list * Spot this and moan loudly. */ if (skb->next != NULL) { NETDEBUG(printk("ip_queue_xmit: next != NULL\n")); skb_unlink(skb); } /* * If the indicated interface is up and running, send the packet. */ ip_statistics.IpOutRequests++; #ifdef CONFIG_IP_ACCT ip_fw_chk(iph,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT); #endif #ifdef CONFIG_IP_MULTICAST /* * Multicasts are looped back for other local users */ if (MULTICAST(iph->daddr) && !(dev->flags&IFF_LOOPBACK)) { if(sk==NULL || sk->ip_mc_loop) { if(iph->daddr==IGMP_ALL_HOSTS || (dev->flags&IFF_ALLMULTI)) { ip_loopback(dev,skb); } else { struct ip_mc_list *imc=dev->ip_mc_list; while(imc!=NULL) { if(imc->multiaddr==iph->daddr) { ip_loopback(dev,skb); break; } imc=imc->next; } } } /* Multicasts with ttl 0 must not go beyond the host */ if (iph->ttl==0) goto out; } #endif if ((dev->flags & IFF_BROADCAST) && !(dev->flags & IFF_LOOPBACK) && (iph->daddr==dev->pa_brdaddr || iph->daddr==0xFFFFFFFF)) ip_loopback(dev,skb); if (dev->flags & IFF_UP) { /* * If we have an owner use its priority setting, * otherwise use NORMAL */ int priority = SOPRI_NORMAL; if (sk) priority = sk->priority; dev_queue_xmit(skb, dev, priority); return; } if(sk) sk->err = ENETDOWN; ip_statistics.IpOutDiscards++; out: if (free) kfree_skb(skb, FREE_WRITE); return; no_device: NETDEBUG(printk("IP: ip_queue_xmit dev = NULL\n")); goto out; fragment: ip_fragment(sk,skb,dev,0); goto out; }