static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len) { struct ec_device *edev = edev_get(skb->dev); struct iphdr *ip = skb->nh.iph; unsigned char stn = ntohl(ip->saddr) & 0xff; struct sock *sk; struct sk_buff *newskb; struct ec_cb *eb; struct sockaddr_ec *sec; if (edev == NULL) return; /* Device not configured for AUN */ if ((sk = ec_listening_socket(ah->port, stn, edev->net)) == NULL) goto bad; /* Nobody wants it */ newskb = alloc_skb((len - sizeof(struct aunhdr) + 15) & ~15, GFP_ATOMIC); if (newskb == NULL) { printk(KERN_DEBUG "AUN: memory squeeze, dropping packet.\n"); /* Send nack and hope sender tries again */ goto bad; } eb = (struct ec_cb *)&newskb->cb; sec = (struct sockaddr_ec *)&eb->sec; memset(sec, 0, sizeof(struct sockaddr_ec)); sec->sec_family = AF_ECONET; sec->type = ECTYPE_PACKET_RECEIVED; sec->port = ah->port; sec->cb = ah->cb; sec->addr.net = edev->net; sec->addr.station = stn; memcpy(skb_put(newskb, len - sizeof(struct aunhdr)), (void *)(ah+1), len - sizeof(struct aunhdr)); if (sock_queue_rcv_skb(sk, newskb) < 0) { /* Socket is bankrupt. */ kfree_skb(newskb); goto bad; } aun_send_response(ip->saddr, ah->handle, 3, 0); return; bad: aun_send_response(ip->saddr, ah->handle, 4, 0); }
static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len) { struct iphdr *ip = skb->nh.iph; unsigned char stn = ntohl(ip->saddr) & 0xff; struct sock *sk; struct sk_buff *newskb; struct ec_device *edev = skb->dev->ec_ptr; if (! edev) goto bad; if ((sk = ec_listening_socket(ah->port, stn, edev->net)) == NULL) goto bad; /* Nobody wants it */ newskb = alloc_skb((len - sizeof(struct aunhdr) + 15) & ~15, GFP_ATOMIC); if (newskb == NULL) { printk(KERN_DEBUG "AUN: memory squeeze, dropping packet.\n"); /* Send nack and hope sender tries again */ goto bad; } memcpy(skb_put(newskb, len - sizeof(struct aunhdr)), (void *)(ah+1), len - sizeof(struct aunhdr)); if (ec_queue_packet(sk, newskb, stn, edev->net, ah->cb, ah->port)) { /* Socket is bankrupt. */ kfree_skb(newskb); goto bad; } aun_send_response(ip->saddr, ah->handle, 3, 0); return; bad: aun_send_response(ip->saddr, ah->handle, 4, 0); }
static void aun_data_available(struct sock *sk, int slen) { int err; struct sk_buff *skb; unsigned char *data; struct aunhdr *ah; struct iphdr *ip; size_t len; while ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL) { if (err == -EAGAIN) { printk(KERN_ERR "AUN: no data available?!"); return; } printk(KERN_DEBUG "AUN: recvfrom() error %d\n", -err); } data = skb->h.raw + sizeof(struct udphdr); ah = (struct aunhdr *)data; len = skb->len - sizeof(struct udphdr); ip = skb->nh.iph; switch (ah->code) { case 2: aun_incoming(skb, ah, len); break; case 3: aun_tx_ack(ah->handle, ECTYPE_TRANSMIT_OK); break; case 4: aun_tx_ack(ah->handle, ECTYPE_TRANSMIT_NOT_LISTENING); break; #if 0 /* This isn't quite right yet. */ case 5: aun_send_response(ip->saddr, ah->handle, 6, ah->cb); break; #endif default: printk(KERN_DEBUG "unknown AUN packet (type %d)\n", data[0]); } skb_free_datagram(sk, skb); }