ip_queue.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:17k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * This is a module which is used for queueing IPv4 packets and
  3.  * communicating with userspace via netlink.
  4.  *
  5.  * (C) 2000 James Morris, this code is GPL.
  6.  *
  7.  * 2000-03-27: Simplified code (thanks to Andi Kleen for clues).
  8.  * 2000-05-20: Fixed notifier problems (following Miguel Freitas' report).
  9.  * 2000-06-19: Fixed so nfmark is copied to metadata (reported by Sebastian 
  10.  *             Zander).
  11.  * 2000-08-01: Added Nick Williams' MAC support.
  12.  *
  13.  */
  14. #include <linux/module.h>
  15. #include <linux/skbuff.h>
  16. #include <linux/init.h>
  17. #include <linux/ip.h>
  18. #include <linux/notifier.h>
  19. #include <linux/netdevice.h>
  20. #include <linux/netfilter.h>
  21. #include <linux/netlink.h>
  22. #include <linux/spinlock.h>
  23. #include <linux/rtnetlink.h>
  24. #include <linux/sysctl.h>
  25. #include <linux/proc_fs.h>
  26. #include <net/sock.h>
  27. #include <net/route.h>
  28. #include <linux/netfilter_ipv4/ip_queue.h>
  29. #include <linux/netfilter_ipv4/ip_tables.h>
  30. #define IPQ_QMAX_DEFAULT 1024
  31. #define IPQ_PROC_FS_NAME "ip_queue"
  32. #define NET_IPQ_QMAX 2088
  33. #define NET_IPQ_QMAX_NAME "ip_queue_maxlen"
  34. typedef struct ipq_rt_info {
  35. __u8 tos;
  36. __u32 daddr;
  37. __u32 saddr;
  38. } ipq_rt_info_t;
  39. typedef struct ipq_queue_element {
  40. struct list_head list; /* Links element into queue */
  41. int verdict; /* Current verdict */
  42. struct nf_info *info; /* Extra info from netfilter */
  43. struct sk_buff *skb; /* Packet inside */
  44. ipq_rt_info_t rt_info; /* May need post-mangle routing */
  45. } ipq_queue_element_t;
  46. typedef int (*ipq_send_cb_t)(ipq_queue_element_t *e);
  47. typedef struct ipq_peer {
  48. pid_t pid; /* PID of userland peer */
  49. unsigned char died; /* We think the peer died */
  50. unsigned char copy_mode; /* Copy packet as well as metadata? */
  51. size_t copy_range; /* Range past metadata to copy */
  52. ipq_send_cb_t send; /* Callback for sending data to peer */
  53. } ipq_peer_t;
  54. typedef struct ipq_queue {
  55.   int len; /* Current queue len */
  56.   int *maxlen; /* Maximum queue len, via sysctl */
  57.   unsigned char flushing; /* If queue is being flushed */
  58.   unsigned char terminate; /* If the queue is being terminated */
  59.   struct list_head list; /* Head of packet queue */
  60.   spinlock_t lock; /* Queue spinlock */
  61.   ipq_peer_t peer; /* Userland peer */
  62. } ipq_queue_t;
  63. /****************************************************************************
  64.  *
  65.  * Packet queue
  66.  *
  67.  ****************************************************************************/
  68. /* Dequeue a packet if matched by cmp, or the next available if cmp is NULL */
  69. static ipq_queue_element_t *
  70. ipq_dequeue(ipq_queue_t *q,
  71.             int (*cmp)(ipq_queue_element_t *, unsigned long),
  72.             unsigned long data)
  73. {
  74. struct list_head *i;
  75. spin_lock_bh(&q->lock);
  76. for (i = q->list.prev; i != &q->list; i = i->prev) {
  77. ipq_queue_element_t *e = (ipq_queue_element_t *)i;
  78. if (!cmp || cmp(e, data)) {
  79. list_del(&e->list);
  80. q->len--;
  81. spin_unlock_bh(&q->lock);
  82. return e;
  83. }
  84. }
  85. spin_unlock_bh(&q->lock);
  86. return NULL;
  87. }
  88. /* Flush all packets */
  89. static void ipq_flush(ipq_queue_t *q)
  90. {
  91. ipq_queue_element_t *e;
  92. spin_lock_bh(&q->lock);
  93. q->flushing = 1;
  94. spin_unlock_bh(&q->lock);
  95. while ((e = ipq_dequeue(q, NULL, 0))) {
  96. e->verdict = NF_DROP;
  97. nf_reinject(e->skb, e->info, e->verdict);
  98. kfree(e);
  99. }
  100. spin_lock_bh(&q->lock);
  101. q->flushing = 0;
  102. spin_unlock_bh(&q->lock);
  103. }
  104. static ipq_queue_t *ipq_create_queue(nf_queue_outfn_t outfn,
  105.                                      ipq_send_cb_t send_cb,
  106.                                      int *errp, int *sysctl_qmax)
  107. {
  108. int status;
  109. ipq_queue_t *q;
  110. *errp = 0;
  111. q = kmalloc(sizeof(ipq_queue_t), GFP_KERNEL);
  112. if (q == NULL) {
  113. *errp = -ENOMEM;
  114. return NULL;
  115. }
  116. q->peer.pid = 0;
  117. q->peer.died = 0;
  118. q->peer.copy_mode = IPQ_COPY_NONE;
  119. q->peer.copy_range = 0;
  120. q->peer.send = send_cb;
  121. q->len = 0;
  122. q->maxlen = sysctl_qmax;
  123. q->flushing = 0;
  124. q->terminate = 0;
  125. INIT_LIST_HEAD(&q->list);
  126. spin_lock_init(&q->lock);
  127. status = nf_register_queue_handler(PF_INET, outfn, q);
  128. if (status < 0) {
  129. *errp = -EBUSY;
  130. kfree(q);
  131. return NULL;
  132. }
  133. return q;
  134. }
  135. static int ipq_enqueue(ipq_queue_t *q,
  136.                        struct sk_buff *skb, struct nf_info *info)
  137. {
  138. ipq_queue_element_t *e;
  139. int status;
  140. e = kmalloc(sizeof(*e), GFP_ATOMIC);
  141. if (e == NULL) {
  142. printk(KERN_ERR "ip_queue: OOM in enqueuen");
  143. return -ENOMEM;
  144. }
  145. e->verdict = NF_DROP;
  146. e->info = info;
  147. e->skb = skb;
  148. if (e->info->hook == NF_IP_LOCAL_OUT) {
  149. struct iphdr *iph = skb->nh.iph;
  150. e->rt_info.tos = iph->tos;
  151. e->rt_info.daddr = iph->daddr;
  152. e->rt_info.saddr = iph->saddr;
  153. }
  154. spin_lock_bh(&q->lock);
  155. if (q->len >= *q->maxlen) {
  156. spin_unlock_bh(&q->lock);
  157. if (net_ratelimit()) 
  158. printk(KERN_WARNING "ip_queue: full at %d entries, "
  159.        "dropping packet(s).n", q->len);
  160. goto free_drop;
  161. }
  162. if (q->flushing || q->peer.copy_mode == IPQ_COPY_NONE
  163.     || q->peer.pid == 0 || q->peer.died || q->terminate) {
  164. spin_unlock_bh(&q->lock);
  165. goto free_drop;
  166. }
  167. status = q->peer.send(e);
  168. if (status > 0) {
  169. list_add(&e->list, &q->list);
  170. q->len++;
  171. spin_unlock_bh(&q->lock);
  172. return status;
  173. }
  174. spin_unlock_bh(&q->lock);
  175. if (status == -ECONNREFUSED) {
  176. printk(KERN_INFO "ip_queue: peer %d died, "
  177.        "resetting state and flushing queuen", q->peer.pid);
  178. q->peer.died = 1;
  179. q->peer.pid = 0;
  180. q->peer.copy_mode = IPQ_COPY_NONE;
  181. q->peer.copy_range = 0;
  182. ipq_flush(q);
  183. }
  184. free_drop:
  185. kfree(e);
  186. return -EBUSY;
  187. }
  188. static void ipq_destroy_queue(ipq_queue_t *q)
  189. {
  190. nf_unregister_queue_handler(PF_INET);
  191. spin_lock_bh(&q->lock);
  192. q->terminate = 1;
  193. spin_unlock_bh(&q->lock);
  194. ipq_flush(q);
  195. kfree(q);
  196. }
  197. static int ipq_mangle_ipv4(ipq_verdict_msg_t *v, ipq_queue_element_t *e)
  198. {
  199. int diff;
  200. struct iphdr *user_iph = (struct iphdr *)v->payload;
  201. if (v->data_len < sizeof(*user_iph))
  202. return 0;
  203. diff = v->data_len - e->skb->len;
  204. if (diff < 0)
  205. skb_trim(e->skb, v->data_len);
  206. else if (diff > 0) {
  207. if (v->data_len > 0xFFFF)
  208. return -EINVAL;
  209. if (diff > skb_tailroom(e->skb)) {
  210. struct sk_buff *newskb;
  211. newskb = skb_copy_expand(e->skb,
  212.                          skb_headroom(e->skb),
  213.                          diff,
  214.                          GFP_ATOMIC);
  215. if (newskb == NULL) {
  216. printk(KERN_WARNING "ip_queue: OOM "
  217.       "in mangle, dropping packetn");
  218. return -ENOMEM;
  219. }
  220. if (e->skb->sk)
  221. skb_set_owner_w(newskb, e->skb->sk);
  222. kfree_skb(e->skb);
  223. e->skb = newskb;
  224. }
  225. skb_put(e->skb, diff);
  226. }
  227. memcpy(e->skb->data, v->payload, v->data_len);
  228. e->skb->nfcache |= NFC_ALTERED;
  229. /*
  230.  * Extra routing may needed on local out, as the QUEUE target never
  231.  * returns control to the table.
  232.  */
  233. if (e->info->hook == NF_IP_LOCAL_OUT) {
  234. struct iphdr *iph = e->skb->nh.iph;
  235. if (!(iph->tos == e->rt_info.tos
  236.       && iph->daddr == e->rt_info.daddr
  237.       && iph->saddr == e->rt_info.saddr))
  238. return ip_route_me_harder(&e->skb);
  239. }
  240. return 0;
  241. }
  242. static inline int id_cmp(ipq_queue_element_t *e, unsigned long id)
  243. {
  244. return (id == (unsigned long )e);
  245. }
  246. static int ipq_set_verdict(ipq_queue_t *q,
  247.                            ipq_verdict_msg_t *v, unsigned int len)
  248. {
  249. ipq_queue_element_t *e;
  250. if (v->value > NF_MAX_VERDICT)
  251. return -EINVAL;
  252. e = ipq_dequeue(q, id_cmp, v->id);
  253. if (e == NULL)
  254. return -ENOENT;
  255. else {
  256. e->verdict = v->value;
  257. if (v->data_len && v->data_len == len)
  258. if (ipq_mangle_ipv4(v, e) < 0)
  259. e->verdict = NF_DROP;
  260. nf_reinject(e->skb, e->info, e->verdict);
  261. kfree(e);
  262. return 0;
  263. }
  264. }
  265. static int ipq_receive_peer(ipq_queue_t *q, ipq_peer_msg_t *m,
  266.                             unsigned char type, unsigned int len)
  267. {
  268. int status = 0;
  269. int busy;
  270. spin_lock_bh(&q->lock);
  271. busy = (q->terminate || q->flushing);
  272. spin_unlock_bh(&q->lock);
  273. if (busy)
  274. return -EBUSY;
  275. if (len < sizeof(ipq_peer_msg_t))
  276. return -EINVAL;
  277. switch (type) {
  278. case IPQM_MODE:
  279. switch (m->msg.mode.value) {
  280. case IPQ_COPY_META:
  281. q->peer.copy_mode = IPQ_COPY_META;
  282. q->peer.copy_range = 0;
  283. break;
  284. case IPQ_COPY_PACKET:
  285. q->peer.copy_mode = IPQ_COPY_PACKET;
  286. q->peer.copy_range = m->msg.mode.range;
  287. if (q->peer.copy_range > 0xFFFF)
  288. q->peer.copy_range = 0xFFFF;
  289. break;
  290. default:
  291. status = -EINVAL;
  292. }
  293. break;
  294. case IPQM_VERDICT:
  295. if (m->msg.verdict.value > NF_MAX_VERDICT)
  296. status = -EINVAL;
  297. else
  298. status = ipq_set_verdict(q,
  299.                          &m->msg.verdict,
  300.                          len - sizeof(*m));
  301. break;
  302. default:
  303.  status = -EINVAL;
  304. }
  305. return status;
  306. }
  307. static inline int dev_cmp(ipq_queue_element_t *e, unsigned long ifindex)
  308. {
  309. if (e->info->indev)
  310. if (e->info->indev->ifindex == ifindex)
  311. return 1;
  312. if (e->info->outdev)
  313. if (e->info->outdev->ifindex == ifindex)
  314. return 1;
  315. return 0;
  316. }
  317. /* Drop any queued packets associated with device ifindex */
  318. static void ipq_dev_drop(ipq_queue_t *q, int ifindex)
  319. {
  320. ipq_queue_element_t *e;
  321. while ((e = ipq_dequeue(q, dev_cmp, ifindex))) {
  322. e->verdict = NF_DROP;
  323. nf_reinject(e->skb, e->info, e->verdict);
  324. kfree(e);
  325. }
  326. }
  327. /****************************************************************************
  328.  *
  329.  * Netfilter interface
  330.  *
  331.  ****************************************************************************/
  332. /*
  333.  * Packets arrive here from netfilter for queuing to userspace.
  334.  * All of them must be fed back via nf_reinject() or Alexey will kill Rusty.
  335.  */
  336. static int netfilter_receive(struct sk_buff *skb,
  337.                              struct nf_info *info, void *data)
  338. {
  339. return ipq_enqueue((ipq_queue_t *)data, skb, info);
  340. }
  341. /****************************************************************************
  342.  *
  343.  * Netlink interface.
  344.  *
  345.  ****************************************************************************/
  346. static struct sock *nfnl = NULL;
  347. ipq_queue_t *nlq = NULL;
  348. static struct sk_buff *netlink_build_message(ipq_queue_element_t *e, int *errp)
  349. {
  350. unsigned char *old_tail;
  351. size_t size = 0;
  352. size_t data_len = 0;
  353. struct sk_buff *skb;
  354. ipq_packet_msg_t *pm;
  355. struct nlmsghdr *nlh;
  356. switch (nlq->peer.copy_mode) {
  357. size_t copy_range;
  358. case IPQ_COPY_META:
  359. size = NLMSG_SPACE(sizeof(*pm));
  360. data_len = 0;
  361. break;
  362. case IPQ_COPY_PACKET:
  363. copy_range = nlq->peer.copy_range;
  364. if (copy_range == 0 || copy_range > e->skb->len)
  365. data_len = e->skb->len;
  366. else
  367. data_len = copy_range;
  368. size = NLMSG_SPACE(sizeof(*pm) + data_len);
  369. break;
  370. case IPQ_COPY_NONE:
  371. default:
  372. *errp = -EINVAL;
  373. return NULL;
  374. }
  375. skb = alloc_skb(size, GFP_ATOMIC);
  376. if (!skb)
  377. goto nlmsg_failure;
  378. old_tail = skb->tail;
  379. nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh));
  380. pm = NLMSG_DATA(nlh);
  381. memset(pm, 0, sizeof(*pm));
  382. pm->packet_id = (unsigned long )e;
  383. pm->data_len = data_len;
  384. pm->timestamp_sec = e->skb->stamp.tv_sec;
  385. pm->timestamp_usec = e->skb->stamp.tv_usec;
  386. pm->mark = e->skb->nfmark;
  387. pm->hook = e->info->hook;
  388. if (e->info->indev) strcpy(pm->indev_name, e->info->indev->name);
  389. else pm->indev_name[0] = '';
  390. if (e->info->outdev) strcpy(pm->outdev_name, e->info->outdev->name);
  391. else pm->outdev_name[0] = '';
  392. pm->hw_protocol = e->skb->protocol;
  393. if (e->info->indev && e->skb->dev) {
  394. pm->hw_type = e->skb->dev->type;
  395. if (e->skb->dev->hard_header_parse)
  396. pm->hw_addrlen =
  397. e->skb->dev->hard_header_parse(e->skb,
  398.                                pm->hw_addr);
  399. }
  400. if (data_len)
  401. memcpy(pm->payload, e->skb->data, data_len);
  402. nlh->nlmsg_len = skb->tail - old_tail;
  403. NETLINK_CB(skb).dst_groups = 0;
  404. return skb;
  405. nlmsg_failure:
  406. if (skb)
  407. kfree_skb(skb);
  408. *errp = 0;
  409. printk(KERN_ERR "ip_queue: error creating netlink messagen");
  410. return NULL;
  411. }
  412. static int netlink_send_peer(ipq_queue_element_t *e)
  413. {
  414. int status = 0;
  415. struct sk_buff *skb;
  416. skb = netlink_build_message(e, &status);
  417. if (skb == NULL)
  418. return status;
  419. return netlink_unicast(nfnl, skb, nlq->peer.pid, MSG_DONTWAIT);
  420. }
  421. #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0);
  422. static __inline__ void netlink_receive_user_skb(struct sk_buff *skb)
  423. {
  424. int status, type;
  425. struct nlmsghdr *nlh;
  426. if (skb->len < sizeof(struct nlmsghdr))
  427. return;
  428. nlh = (struct nlmsghdr *)skb->data;
  429. if (nlh->nlmsg_len < sizeof(struct nlmsghdr)
  430.     || skb->len < nlh->nlmsg_len)
  431.      return;
  432. if(nlh->nlmsg_pid <= 0
  433.     || !(nlh->nlmsg_flags & NLM_F_REQUEST)
  434.     || nlh->nlmsg_flags & NLM_F_MULTI)
  435. RCV_SKB_FAIL(-EINVAL);
  436. if (nlh->nlmsg_flags & MSG_TRUNC)
  437. RCV_SKB_FAIL(-ECOMM);
  438. type = nlh->nlmsg_type;
  439. if (type < NLMSG_NOOP || type >= IPQM_MAX)
  440. RCV_SKB_FAIL(-EINVAL);
  441. if (type <= IPQM_BASE)
  442. return;
  443. if(!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
  444. RCV_SKB_FAIL(-EPERM);
  445. if (nlq->peer.pid && !nlq->peer.died
  446.     && (nlq->peer.pid != nlh->nlmsg_pid)) {
  447.      printk(KERN_WARNING "ip_queue: peer pid changed from %d to "
  448.            "%d, flushing queuen", nlq->peer.pid, nlh->nlmsg_pid);
  449. ipq_flush(nlq);
  450. }
  451. nlq->peer.pid = nlh->nlmsg_pid;
  452. nlq->peer.died = 0;
  453. status = ipq_receive_peer(nlq, NLMSG_DATA(nlh),
  454.                           type, skb->len - NLMSG_LENGTH(0));
  455. if (status < 0)
  456. RCV_SKB_FAIL(status);
  457. if (nlh->nlmsg_flags & NLM_F_ACK)
  458. netlink_ack(skb, nlh, 0);
  459.         return;
  460. }
  461. /* Note: we are only dealing with single part messages at the moment. */
  462. static void netlink_receive_user_sk(struct sock *sk, int len)
  463. {
  464. do {
  465. struct sk_buff *skb;
  466. if (rtnl_shlock_nowait())
  467. return;
  468. while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
  469. netlink_receive_user_skb(skb);
  470. kfree_skb(skb);
  471. }
  472. up(&rtnl_sem);
  473. } while (nfnl && nfnl->receive_queue.qlen);
  474. }
  475. /****************************************************************************
  476.  *
  477.  * System events
  478.  *
  479.  ****************************************************************************/
  480. static int receive_event(struct notifier_block *this,
  481.                          unsigned long event, void *ptr)
  482. {
  483. struct net_device *dev = ptr;
  484. /* Drop any packets associated with the downed device */
  485. if (event == NETDEV_DOWN)
  486. ipq_dev_drop(nlq, dev->ifindex);
  487. return NOTIFY_DONE;
  488. }
  489. struct notifier_block ipq_dev_notifier = {
  490. receive_event,
  491. NULL,
  492. 0
  493. };
  494. /****************************************************************************
  495.  *
  496.  * Sysctl - queue tuning.
  497.  *
  498.  ****************************************************************************/
  499. static int sysctl_maxlen = IPQ_QMAX_DEFAULT;
  500. static struct ctl_table_header *ipq_sysctl_header;
  501. static ctl_table ipq_table[] = {
  502. { NET_IPQ_QMAX, NET_IPQ_QMAX_NAME, &sysctl_maxlen,
  503.   sizeof(sysctl_maxlen), 0644,  NULL, proc_dointvec },
  504.   { 0 }
  505. };
  506. static ctl_table ipq_dir_table[] = {
  507. {NET_IPV4, "ipv4", NULL, 0, 0555, ipq_table, 0, 0, 0, 0, 0},
  508. { 0 }
  509. };
  510. static ctl_table ipq_root_table[] = {
  511. {CTL_NET, "net", NULL, 0, 0555, ipq_dir_table, 0, 0, 0, 0, 0},
  512. { 0 }
  513. };
  514. /****************************************************************************
  515.  *
  516.  * Procfs - debugging info.
  517.  *
  518.  ****************************************************************************/
  519. static int ipq_get_info(char *buffer, char **start, off_t offset, int length)
  520. {
  521. int len;
  522. spin_lock_bh(&nlq->lock);
  523. len = sprintf(buffer,
  524.               "Peer pid            : %dn"
  525.               "Peer died           : %dn"
  526.               "Peer copy mode      : %dn"
  527.               "Peer copy range     : %Zun"
  528.               "Queue length        : %dn"
  529.               "Queue max. length   : %dn"
  530.               "Queue flushing      : %dn"
  531.               "Queue terminate     : %dn",
  532.               nlq->peer.pid,
  533.               nlq->peer.died,
  534.               nlq->peer.copy_mode,
  535.               nlq->peer.copy_range,
  536.               nlq->len,
  537.               *nlq->maxlen,
  538.               nlq->flushing,
  539.               nlq->terminate);
  540. spin_unlock_bh(&nlq->lock);
  541. *start = buffer + offset;
  542. len -= offset;
  543. if (len > length)
  544. len = length;
  545. else if (len < 0)
  546. len = 0;
  547. return len;
  548. }
  549. /****************************************************************************
  550.  *
  551.  * Module stuff.
  552.  *
  553.  ****************************************************************************/
  554. static int __init init(void)
  555. {
  556. int status = 0;
  557. struct proc_dir_entry *proc;
  558. nfnl = netlink_kernel_create(NETLINK_FIREWALL, netlink_receive_user_sk);
  559. if (nfnl == NULL) {
  560. printk(KERN_ERR "ip_queue: initialisation failed: unable to "
  561.        "create kernel netlink socketn");
  562. return -ENOMEM;
  563. }
  564. nlq = ipq_create_queue(netfilter_receive,
  565.                        netlink_send_peer, &status, &sysctl_maxlen);
  566. if (nlq == NULL) {
  567. printk(KERN_ERR "ip_queue: initialisation failed: unable to "
  568.        "create queuen");
  569. sock_release(nfnl->socket);
  570. return status;
  571. }
  572. proc = proc_net_create(IPQ_PROC_FS_NAME, 0, ipq_get_info);
  573. if (proc) proc->owner = THIS_MODULE;
  574. else {
  575. ipq_destroy_queue(nlq);
  576. sock_release(nfnl->socket);
  577. return -ENOMEM;
  578. }
  579. register_netdevice_notifier(&ipq_dev_notifier);
  580. ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0);
  581. return status;
  582. }
  583. static void __exit fini(void)
  584. {
  585. unregister_sysctl_table(ipq_sysctl_header);
  586. proc_net_remove(IPQ_PROC_FS_NAME);
  587. unregister_netdevice_notifier(&ipq_dev_notifier);
  588. ipq_destroy_queue(nlq);
  589. sock_release(nfnl->socket);
  590. }
  591. MODULE_DESCRIPTION("IPv4 packet queue handler");
  592. MODULE_LICENSE("GPL");
  593. module_init(init);
  594. module_exit(fini);