00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "packet_queue.h"
00018
00019 #define IPQ_QMAX_DEFAULT 1024
00020 #define IPQ_PROC_FS_NAME "ip_queue"
00021 #define NET_IPQ_QMAX 2088
00022 #define NET_IPQ_QMAX_NAME "ip_queue_maxlen"
00023
00024 typedef struct ipq_rt_info {
00025 __u8 tos;
00026 __u32 daddr;
00027 __u32 saddr;
00028 } ipq_rt_info_t;
00029
00030 typedef struct ipq_queue_element {
00031 struct list_head list;
00032 int verdict;
00033 struct nf_info *info;
00034 struct sk_buff *skb;
00035 ipq_rt_info_t rt_info;
00036 } ipq_queue_element_t;
00037
00038 typedef int (*ipq_send_cb_t)(ipq_queue_element_t *e);
00039
00040 typedef struct ipq_queue {
00041 int len;
00042 int *maxlen;
00043 unsigned char flushing;
00044 unsigned char terminate;
00045 struct list_head list;
00046 spinlock_t lock;
00047 } ipq_queue_t;
00048
00049 static ipq_queue_t *q;
00050 static int netfilter_receive(struct sk_buff *skb, struct nf_info *info, void *data);
00051
00052
00053
00054
00055
00056
00057
00058 static ipq_queue_element_t * ipq_dequeue( int (*cmp)(ipq_queue_element_t *, u_int32_t), u_int32_t data)
00059 {
00060 struct list_head *i;
00061
00062 spin_lock_bh(&q->lock);
00063 for (i = q->list.prev; i != &q->list; i = i->prev) {
00064 ipq_queue_element_t *e = (ipq_queue_element_t *)i;
00065
00066 if (!cmp || cmp(e, data)) {
00067 list_del(&e->list);
00068 q->len--;
00069 spin_unlock_bh(&q->lock);
00070 return e;
00071 }
00072 }
00073 spin_unlock_bh(&q->lock);
00074 return NULL;
00075 }
00076
00077
00078
00079 static void ipq_flush()
00080 {
00081 ipq_queue_element_t *e;
00082
00083 spin_lock_bh(&q->lock);
00084 q->flushing = 1;
00085 spin_unlock_bh(&q->lock);
00086 while ((e = ipq_dequeue( NULL, 0))) {
00087 e->verdict = NF_DROP;
00088 nf_reinject(e->skb, e->info, e->verdict);
00089 kfree(e);
00090 }
00091 spin_lock_bh(&q->lock);
00092 q->flushing = 0;
00093 spin_unlock_bh(&q->lock);
00094 }
00095
00096
00097
00098
00099 static int ipq_create_queue(int *sysctl_qmax)
00100 {
00101 int status;
00102
00103 q = kmalloc(sizeof(ipq_queue_t), GFP_KERNEL);
00104 if (q == NULL) {
00105 return 0;
00106 }
00107 q->len = 0;
00108 q->maxlen = sysctl_qmax;
00109 q->flushing = 0;
00110 q->terminate = 0;
00111 INIT_LIST_HEAD(&q->list);
00112 spin_lock_init(&q->lock);
00113
00114 status = nf_register_queue_handler(PF_INET, netfilter_receive, q);
00115 if (status < 0) {
00116 printk("Could not create Packet Queue! %d\n",status);
00117 kfree(q);
00118 return 0;
00119 }
00120 return 1;
00121 }
00122
00123 static int ipq_enqueue(ipq_queue_t *g,struct sk_buff *skb, struct nf_info *info)
00124 {
00125 ipq_queue_element_t *e;
00126
00127
00128 if (q!=g)
00129 {
00130 printk("trying to enqueue but do not have right queue!!!\n");
00131 return 0;
00132 }
00133
00134 e = kmalloc(sizeof(*e), GFP_ATOMIC);
00135 if (e == NULL) {
00136 printk(KERN_ERR "ip_queue: OOM in enqueue\n");
00137 return -ENOMEM;
00138 }
00139
00140 e->verdict = NF_DROP;
00141 e->info = info;
00142 e->skb = skb;
00143
00144 if (e->info->hook == NF_IP_LOCAL_OUT) {
00145 struct iphdr *iph = skb->nh.iph;
00146
00147 e->rt_info.tos = iph->tos;
00148 e->rt_info.daddr = iph->daddr;
00149 e->rt_info.saddr = iph->saddr;
00150 }
00151
00152 spin_lock_bh(&q->lock);
00153 if (q->len >= *q->maxlen) {
00154 spin_unlock_bh(&q->lock);
00155 if (net_ratelimit())
00156 printk(KERN_WARNING "ip_queue: full at %d entries, "
00157 "dropping packet(s).\n", q->len);
00158 goto free_drop;
00159 }
00160 if (q->flushing || q->terminate) {
00161 spin_unlock_bh(&q->lock);
00162 goto free_drop;
00163 }
00164 list_add(&e->list, &q->list);
00165 q->len++;
00166 spin_unlock_bh(&q->lock);
00167
00168 return q->len;
00169 free_drop:
00170 kfree(e);
00171 return -EBUSY;
00172 }
00173
00174 static void ipq_destroy_queue()
00175 {
00176
00177 nf_unregister_queue_handler(PF_INET);
00178
00179 spin_lock_bh(&q->lock);
00180 q->terminate = 1;
00181 spin_unlock_bh(&q->lock);
00182 ipq_flush();
00183 kfree(q);
00184 }
00185
00186
00187 static int route_me_harder(struct sk_buff *skb)
00188 {
00189 struct iphdr *iph = skb->nh.iph;
00190 struct rtable *rt;
00191
00192 struct rt_key key = {
00193 dst:iph->daddr, src:iph->saddr,
00194 oif:skb->sk ? skb->sk->bound_dev_if : 0,
00195 tos:RT_TOS(iph->tos)|RTO_CONN,
00196 #ifdef CONFIG_IP_ROUTE_FWMARK
00197 fwmark:skb->nfmark
00198 #endif
00199 };
00200
00201 if (ip_route_output_key(&rt, &key) != 0) {
00202 printk("route_me_harder: No more route.\n");
00203 return -EINVAL;
00204 }
00205
00206
00207 dst_release(skb->dst);
00208 skb->dst = &rt->u.dst;
00209 return 0;
00210 }
00211
00212 static inline int id_cmp(ipq_queue_element_t *e,u_int32_t id)
00213 {
00214 return (id == (unsigned long )e);
00215 }
00216
00217
00218 static inline int dev_cmp(ipq_queue_element_t *e, u_int32_t ifindex)
00219 {
00220 if (e->info->indev)
00221 if (e->info->indev->ifindex == ifindex)
00222 return 1;
00223 if (e->info->outdev)
00224 if (e->info->outdev->ifindex == ifindex)
00225 return 1;
00226 return 0;
00227 }
00228
00229 static inline int ip_cmp(ipq_queue_element_t *e, u_int32_t ip)
00230 {
00231
00232 if (e->rt_info.daddr == ip)
00233 return 1;
00234
00235 return 0;
00236 }
00237
00238
00239
00240 static void ipq_dev_drop(int ifindex)
00241 {
00242 ipq_queue_element_t *e;
00243
00244 while ((e = ipq_dequeue(dev_cmp, ifindex))) {
00245 e->verdict = NF_DROP;
00246 nf_reinject(e->skb, e->info, e->verdict);
00247 kfree(e);
00248 }
00249 }
00250
00251 void ipq_send_ip(u_int32_t ip)
00252 {
00253 ipq_queue_element_t *e;
00254
00255 while ((e = ipq_dequeue( ip_cmp, ip))) {
00256 e->verdict = NF_ACCEPT;
00257
00258 e->skb->nfcache |= NFC_ALTERED;
00259 route_me_harder(e->skb);
00260 nf_reinject(e->skb, e->info, e->verdict);
00261
00262 kfree(e);
00263 }
00264 }
00265
00266
00267 void ipq_drop_ip(u_int32_t ip)
00268 {
00269 ipq_queue_element_t *e;
00270
00271 while ((e = ipq_dequeue( ip_cmp, ip))) {
00272
00273 e->verdict = NF_DROP;
00274 icmp_send(e->skb,ICMP_DEST_UNREACH,ICMP_HOST_UNREACH,0);
00275 nf_reinject(e->skb, e->info, e->verdict);
00276 kfree(e);
00277 }
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 int ipq_insert_packet(struct sk_buff *skb,
00292 struct nf_info *info)
00293 {
00294 return ipq_enqueue(q, skb, info);
00295 }
00296
00297
00298 static int netfilter_receive(struct sk_buff *skb,
00299 struct nf_info *info, void *data)
00300 {
00301 return ipq_enqueue((ipq_queue_t *)data, skb, info);
00302 }
00303
00304
00305
00306
00307
00308
00309
00310 static int receive_event(struct notifier_block *this,
00311 unsigned long event, void *ptr)
00312 {
00313 struct net_device *dev = ptr;
00314
00315
00316 if (event == NETDEV_DOWN)
00317 ipq_dev_drop( dev->ifindex);
00318 return NOTIFY_DONE;
00319 }
00320
00321 struct notifier_block ipq_dev_notifier = {
00322 receive_event,
00323 NULL,
00324 0
00325 };
00326
00327
00328
00329
00330
00331
00332
00333 static int sysctl_maxlen = IPQ_QMAX_DEFAULT;
00334
00335 static struct ctl_table_header *ipq_sysctl_header;
00336
00337 static ctl_table ipq_table[] = {
00338 { NET_IPQ_QMAX, NET_IPQ_QMAX_NAME, &sysctl_maxlen,
00339 sizeof(sysctl_maxlen), 0644, NULL, proc_dointvec },
00340 { 0 }
00341 };
00342
00343 static ctl_table ipq_dir_table[] = {
00344 {NET_IPV4, "ipv4", NULL, 0, 0555, ipq_table, 0, 0, 0, 0, 0},
00345 { 0 }
00346 };
00347
00348 static ctl_table ipq_root_table[] = {
00349 {CTL_NET, "net", NULL, 0, 0555, ipq_dir_table, 0, 0, 0, 0, 0},
00350 { 0 }
00351 };
00352
00353
00354
00355
00356
00357
00358
00359 int init_packet_queue(void)
00360 {
00361 int status = 0;
00362
00363
00364 status= ipq_create_queue( &sysctl_maxlen);
00365 if (status == 0) {
00366 printk(KERN_ERR "ip_queue: initialisation failed: unable to "
00367 "create queue\n");
00368
00369 return status;
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379 ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0);
00380 return status;
00381 }
00382
00383 void cleanup_packet_queue(void)
00384 {
00385 unregister_sysctl_table(ipq_sysctl_header);
00386
00387
00388 ipq_destroy_queue(q);
00389
00390 }
00391