diff options
386 files changed, 28243 insertions, 5906 deletions
diff --git a/Documentation/SubmittingDrivers b/Documentation/SubmittingDrivers index dd311cff1cc3..6bd30fdd0786 100644 --- a/Documentation/SubmittingDrivers +++ b/Documentation/SubmittingDrivers | |||
@@ -143,7 +143,7 @@ KernelNewbies: | |||
143 | http://kernelnewbies.org/ | 143 | http://kernelnewbies.org/ |
144 | 144 | ||
145 | Linux USB project: | 145 | Linux USB project: |
146 | http://linux-usb.sourceforge.net/ | 146 | http://www.linux-usb.org/ |
147 | 147 | ||
148 | How to NOT write kernel driver by arjanv@redhat.com | 148 | How to NOT write kernel driver by arjanv@redhat.com |
149 | http://people.redhat.com/arjanv/olspaper.pdf | 149 | http://people.redhat.com/arjanv/olspaper.pdf |
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 6198e5ebcf65..c2c85bcb3d43 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches | |||
@@ -478,10 +478,11 @@ Andrew Morton, "The perfect patch" (tpp). | |||
478 | Jeff Garzik, "Linux kernel patch submission format." | 478 | Jeff Garzik, "Linux kernel patch submission format." |
479 | <http://linux.yyz.us/patch-format.html> | 479 | <http://linux.yyz.us/patch-format.html> |
480 | 480 | ||
481 | Greg Kroah, "How to piss off a kernel subsystem maintainer". | 481 | Greg Kroah-Hartman "How to piss off a kernel subsystem maintainer". |
482 | <http://www.kroah.com/log/2005/03/31/> | 482 | <http://www.kroah.com/log/2005/03/31/> |
483 | <http://www.kroah.com/log/2005/07/08/> | 483 | <http://www.kroah.com/log/2005/07/08/> |
484 | <http://www.kroah.com/log/2005/10/19/> | 484 | <http://www.kroah.com/log/2005/10/19/> |
485 | <http://www.kroah.com/log/2006/01/11/> | ||
485 | 486 | ||
486 | NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!. | 487 | NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!. |
487 | <http://marc.theaimsgroup.com/?l=linux-kernel&m=112112749912944&w=2> | 488 | <http://marc.theaimsgroup.com/?l=linux-kernel&m=112112749912944&w=2> |
diff --git a/MAINTAINERS b/MAINTAINERS index 0db72a36e245..71693c5c3137 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -2519,6 +2519,19 @@ P: Romain Lievin | |||
2519 | M: roms@lpg.ticalc.org | 2519 | M: roms@lpg.ticalc.org |
2520 | S: Maintained | 2520 | S: Maintained |
2521 | 2521 | ||
2522 | TIPC NETWORK LAYER | ||
2523 | P: Per Liden | ||
2524 | M: per.liden@nospam.ericsson.com | ||
2525 | P: Jon Maloy | ||
2526 | M: jon.maloy@nospam.ericsson.com | ||
2527 | P: Allan Stephens | ||
2528 | M: allan.stephens@nospam.windriver.com | ||
2529 | L: tipc-discussion@lists.sourceforge.net | ||
2530 | W: http://tipc.sourceforge.net/ | ||
2531 | W: http://tipc.cslab.ericsson.net/ | ||
2532 | T: git tipc.cslab.ericsson.net:/pub/git/tipc.git | ||
2533 | S: Maintained | ||
2534 | |||
2522 | TLAN NETWORK DRIVER | 2535 | TLAN NETWORK DRIVER |
2523 | P: Samuel Chessman | 2536 | P: Samuel Chessman |
2524 | M: chessman@tux.org | 2537 | M: chessman@tux.org |
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index a346e1833bf2..626cdc83668b 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c | |||
@@ -108,7 +108,6 @@ static struct async_struct *IRQ_ports[NR_IRQS]; | |||
108 | static struct console *console; | 108 | static struct console *console; |
109 | 109 | ||
110 | static unsigned char *tmp_buf; | 110 | static unsigned char *tmp_buf; |
111 | static DECLARE_MUTEX(tmp_buf_sem); | ||
112 | 111 | ||
113 | extern struct console *console_drivers; /* from kernel/printk.c */ | 112 | extern struct console *console_drivers; /* from kernel/printk.c */ |
114 | 113 | ||
@@ -167,15 +166,9 @@ static void receive_chars(struct tty_struct *tty, struct pt_regs *regs) | |||
167 | } | 166 | } |
168 | } | 167 | } |
169 | seen_esc = 0; | 168 | seen_esc = 0; |
170 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; | ||
171 | 169 | ||
172 | *tty->flip.char_buf_ptr = ch; | 170 | if (tty_insert_flip_char(tty, ch, TTY_NORMAL) == 0) |
173 | 171 | break; | |
174 | *tty->flip.flag_buf_ptr = 0; | ||
175 | |||
176 | tty->flip.flag_buf_ptr++; | ||
177 | tty->flip.char_buf_ptr++; | ||
178 | tty->flip.count++; | ||
179 | } | 172 | } |
180 | tty_flip_buffer_push(tty); | 173 | tty_flip_buffer_push(tty); |
181 | } | 174 | } |
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index 2ddbac6f4999..ce423910ca97 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S | |||
@@ -903,5 +903,6 @@ fsyscall_table: | |||
903 | data8 0 | 903 | data8 0 |
904 | data8 0 | 904 | data8 0 |
905 | data8 0 | 905 | data8 0 |
906 | data8 0 // 1280 | ||
906 | 907 | ||
907 | .org fsyscall_table + 8*NR_syscalls // guard against failures to increase NR_syscalls | 908 | .org fsyscall_table + 8*NR_syscalls // guard against failures to increase NR_syscalls |
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S index 2323377e3695..5cd6226f44f2 100644 --- a/arch/ia64/kernel/jprobes.S +++ b/arch/ia64/kernel/jprobes.S | |||
@@ -60,3 +60,30 @@ END(jprobe_break) | |||
60 | GLOBAL_ENTRY(jprobe_inst_return) | 60 | GLOBAL_ENTRY(jprobe_inst_return) |
61 | br.call.sptk.many b0=jprobe_break | 61 | br.call.sptk.many b0=jprobe_break |
62 | END(jprobe_inst_return) | 62 | END(jprobe_inst_return) |
63 | |||
64 | GLOBAL_ENTRY(invalidate_stacked_regs) | ||
65 | movl r16=invalidate_restore_cfm | ||
66 | ;; | ||
67 | mov b6=r16 | ||
68 | ;; | ||
69 | br.ret.sptk.many b6 | ||
70 | ;; | ||
71 | invalidate_restore_cfm: | ||
72 | mov r16=ar.rsc | ||
73 | ;; | ||
74 | mov ar.rsc=r0 | ||
75 | ;; | ||
76 | loadrs | ||
77 | ;; | ||
78 | mov ar.rsc=r16 | ||
79 | ;; | ||
80 | br.cond.sptk.many rp | ||
81 | END(invalidate_stacked_regs) | ||
82 | |||
83 | GLOBAL_ENTRY(flush_register_stack) | ||
84 | // flush dirty regs to backing store (must be first in insn group) | ||
85 | flushrs | ||
86 | ;; | ||
87 | br.ret.sptk.many rp | ||
88 | END(flush_register_stack) | ||
89 | |||
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 346fedf9ea47..50ae8c7d453d 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c | |||
@@ -766,11 +766,56 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
766 | return ret; | 766 | return ret; |
767 | } | 767 | } |
768 | 768 | ||
769 | struct param_bsp_cfm { | ||
770 | unsigned long ip; | ||
771 | unsigned long *bsp; | ||
772 | unsigned long cfm; | ||
773 | }; | ||
774 | |||
775 | static void ia64_get_bsp_cfm(struct unw_frame_info *info, void *arg) | ||
776 | { | ||
777 | unsigned long ip; | ||
778 | struct param_bsp_cfm *lp = arg; | ||
779 | |||
780 | do { | ||
781 | unw_get_ip(info, &ip); | ||
782 | if (ip == 0) | ||
783 | break; | ||
784 | if (ip == lp->ip) { | ||
785 | unw_get_bsp(info, (unsigned long*)&lp->bsp); | ||
786 | unw_get_cfm(info, (unsigned long*)&lp->cfm); | ||
787 | return; | ||
788 | } | ||
789 | } while (unw_unwind(info) >= 0); | ||
790 | lp->bsp = 0; | ||
791 | lp->cfm = 0; | ||
792 | return; | ||
793 | } | ||
794 | |||
769 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 795 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) |
770 | { | 796 | { |
771 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 797 | struct jprobe *jp = container_of(p, struct jprobe, kp); |
772 | unsigned long addr = ((struct fnptr *)(jp->entry))->ip; | 798 | unsigned long addr = ((struct fnptr *)(jp->entry))->ip; |
773 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 799 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
800 | struct param_bsp_cfm pa; | ||
801 | int bytes; | ||
802 | |||
803 | /* | ||
804 | * Callee owns the argument space and could overwrite it, eg | ||
805 | * tail call optimization. So to be absolutely safe | ||
806 | * we save the argument space before transfering the control | ||
807 | * to instrumented jprobe function which runs in | ||
808 | * the process context | ||
809 | */ | ||
810 | pa.ip = regs->cr_iip; | ||
811 | unw_init_running(ia64_get_bsp_cfm, &pa); | ||
812 | bytes = (char *)ia64_rse_skip_regs(pa.bsp, pa.cfm & 0x3f) | ||
813 | - (char *)pa.bsp; | ||
814 | memcpy( kcb->jprobes_saved_stacked_regs, | ||
815 | pa.bsp, | ||
816 | bytes ); | ||
817 | kcb->bsp = pa.bsp; | ||
818 | kcb->cfm = pa.cfm; | ||
774 | 819 | ||
775 | /* save architectural state */ | 820 | /* save architectural state */ |
776 | kcb->jprobe_saved_regs = *regs; | 821 | kcb->jprobe_saved_regs = *regs; |
@@ -792,8 +837,20 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
792 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | 837 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) |
793 | { | 838 | { |
794 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 839 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
840 | int bytes; | ||
795 | 841 | ||
842 | /* restoring architectural state */ | ||
796 | *regs = kcb->jprobe_saved_regs; | 843 | *regs = kcb->jprobe_saved_regs; |
844 | |||
845 | /* restoring the original argument space */ | ||
846 | flush_register_stack(); | ||
847 | bytes = (char *)ia64_rse_skip_regs(kcb->bsp, kcb->cfm & 0x3f) | ||
848 | - (char *)kcb->bsp; | ||
849 | memcpy( kcb->bsp, | ||
850 | kcb->jprobes_saved_stacked_regs, | ||
851 | bytes ); | ||
852 | invalidate_stacked_regs(); | ||
853 | |||
797 | preempt_enable_no_resched(); | 854 | preempt_enable_no_resched(); |
798 | return 1; | 855 | return 1; |
799 | } | 856 | } |
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S index db32fc1d3935..403a80a58c13 100644 --- a/arch/ia64/kernel/mca_asm.S +++ b/arch/ia64/kernel/mca_asm.S | |||
@@ -847,7 +847,7 @@ ia64_state_restore: | |||
847 | ;; | 847 | ;; |
848 | mov cr.iim=temp3 | 848 | mov cr.iim=temp3 |
849 | mov cr.iha=temp4 | 849 | mov cr.iha=temp4 |
850 | dep r22=0,r22,62,2 // pal_min_state, physical, uncached | 850 | dep r22=0,r22,62,1 // pal_min_state, physical, uncached |
851 | mov IA64_KR(CURRENT)=r21 | 851 | mov IA64_KR(CURRENT)=r21 |
852 | ld8 r8=[temp1] // os_status | 852 | ld8 r8=[temp1] // os_status |
853 | ld8 r10=[temp2] // context | 853 | ld8 r10=[temp2] // context |
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index a87a162a3086..9d5a823479a3 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Creates entries in /proc/sal for various system features. | 4 | * Creates entries in /proc/sal for various system features. |
5 | * | 5 | * |
6 | * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved. | 6 | * Copyright (c) 2003, 2006 Silicon Graphics, Inc. All rights reserved. |
7 | * Copyright (c) 2003 Hewlett-Packard Co | 7 | * Copyright (c) 2003 Hewlett-Packard Co |
8 | * Bjorn Helgaas <bjorn.helgaas@hp.com> | 8 | * Bjorn Helgaas <bjorn.helgaas@hp.com> |
9 | * | 9 | * |
@@ -27,9 +27,17 @@ | |||
27 | * mca.c may not pass a buffer, a NULL buffer just indicates that a new | 27 | * mca.c may not pass a buffer, a NULL buffer just indicates that a new |
28 | * record is available in SAL. | 28 | * record is available in SAL. |
29 | * Replace some NR_CPUS by cpus_online, for hotplug cpu. | 29 | * Replace some NR_CPUS by cpus_online, for hotplug cpu. |
30 | * | ||
31 | * Jan 5 2006 kaos@sgi.com | ||
32 | * Handle hotplug cpus coming online. | ||
33 | * Handle hotplug cpus going offline while they still have outstanding records. | ||
34 | * Use the cpu_* macros consistently. | ||
35 | * Replace the counting semaphore with a mutex and a test if the cpumask is non-empty. | ||
36 | * Modify the locking to make the test for "work to do" an atomic operation. | ||
30 | */ | 37 | */ |
31 | 38 | ||
32 | #include <linux/capability.h> | 39 | #include <linux/capability.h> |
40 | #include <linux/cpu.h> | ||
33 | #include <linux/types.h> | 41 | #include <linux/types.h> |
34 | #include <linux/proc_fs.h> | 42 | #include <linux/proc_fs.h> |
35 | #include <linux/module.h> | 43 | #include <linux/module.h> |
@@ -132,8 +140,8 @@ enum salinfo_state { | |||
132 | }; | 140 | }; |
133 | 141 | ||
134 | struct salinfo_data { | 142 | struct salinfo_data { |
135 | volatile cpumask_t cpu_event; /* which cpus have outstanding events */ | 143 | cpumask_t cpu_event; /* which cpus have outstanding events */ |
136 | struct semaphore sem; /* count of cpus with outstanding events (bits set in cpu_event) */ | 144 | struct semaphore mutex; |
137 | u8 *log_buffer; | 145 | u8 *log_buffer; |
138 | u64 log_size; | 146 | u64 log_size; |
139 | u8 *oemdata; /* decoded oem data */ | 147 | u8 *oemdata; /* decoded oem data */ |
@@ -174,6 +182,21 @@ struct salinfo_platform_oemdata_parms { | |||
174 | int ret; | 182 | int ret; |
175 | }; | 183 | }; |
176 | 184 | ||
185 | /* Kick the mutex that tells user space that there is work to do. Instead of | ||
186 | * trying to track the state of the mutex across multiple cpus, in user | ||
187 | * context, interrupt context, non-maskable interrupt context and hotplug cpu, | ||
188 | * it is far easier just to grab the mutex if it is free then release it. | ||
189 | * | ||
190 | * This routine must be called with data_saved_lock held, to make the down/up | ||
191 | * operation atomic. | ||
192 | */ | ||
193 | static void | ||
194 | salinfo_work_to_do(struct salinfo_data *data) | ||
195 | { | ||
196 | down_trylock(&data->mutex); | ||
197 | up(&data->mutex); | ||
198 | } | ||
199 | |||
177 | static void | 200 | static void |
178 | salinfo_platform_oemdata_cpu(void *context) | 201 | salinfo_platform_oemdata_cpu(void *context) |
179 | { | 202 | { |
@@ -212,9 +235,9 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe) | |||
212 | 235 | ||
213 | BUG_ON(type >= ARRAY_SIZE(salinfo_log_name)); | 236 | BUG_ON(type >= ARRAY_SIZE(salinfo_log_name)); |
214 | 237 | ||
238 | if (irqsafe) | ||
239 | spin_lock_irqsave(&data_saved_lock, flags); | ||
215 | if (buffer) { | 240 | if (buffer) { |
216 | if (irqsafe) | ||
217 | spin_lock_irqsave(&data_saved_lock, flags); | ||
218 | for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) { | 241 | for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) { |
219 | if (!data_saved->buffer) | 242 | if (!data_saved->buffer) |
220 | break; | 243 | break; |
@@ -232,13 +255,11 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe) | |||
232 | data_saved->size = size; | 255 | data_saved->size = size; |
233 | data_saved->buffer = buffer; | 256 | data_saved->buffer = buffer; |
234 | } | 257 | } |
235 | if (irqsafe) | ||
236 | spin_unlock_irqrestore(&data_saved_lock, flags); | ||
237 | } | 258 | } |
238 | 259 | cpu_set(smp_processor_id(), data->cpu_event); | |
239 | if (!test_and_set_bit(smp_processor_id(), &data->cpu_event)) { | 260 | if (irqsafe) { |
240 | if (irqsafe) | 261 | salinfo_work_to_do(data); |
241 | up(&data->sem); | 262 | spin_unlock_irqrestore(&data_saved_lock, flags); |
242 | } | 263 | } |
243 | } | 264 | } |
244 | 265 | ||
@@ -249,20 +270,17 @@ static struct timer_list salinfo_timer; | |||
249 | static void | 270 | static void |
250 | salinfo_timeout_check(struct salinfo_data *data) | 271 | salinfo_timeout_check(struct salinfo_data *data) |
251 | { | 272 | { |
252 | int i; | 273 | unsigned long flags; |
253 | if (!data->open) | 274 | if (!data->open) |
254 | return; | 275 | return; |
255 | for_each_online_cpu(i) { | 276 | if (!cpus_empty(data->cpu_event)) { |
256 | if (test_bit(i, &data->cpu_event)) { | 277 | spin_lock_irqsave(&data_saved_lock, flags); |
257 | /* double up() is not a problem, user space will see no | 278 | salinfo_work_to_do(data); |
258 | * records for the additional "events". | 279 | spin_unlock_irqrestore(&data_saved_lock, flags); |
259 | */ | ||
260 | up(&data->sem); | ||
261 | } | ||
262 | } | 280 | } |
263 | } | 281 | } |
264 | 282 | ||
265 | static void | 283 | static void |
266 | salinfo_timeout (unsigned long arg) | 284 | salinfo_timeout (unsigned long arg) |
267 | { | 285 | { |
268 | salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA); | 286 | salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA); |
@@ -290,16 +308,20 @@ salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t | |||
290 | int i, n, cpu = -1; | 308 | int i, n, cpu = -1; |
291 | 309 | ||
292 | retry: | 310 | retry: |
293 | if (down_trylock(&data->sem)) { | 311 | if (cpus_empty(data->cpu_event) && down_trylock(&data->mutex)) { |
294 | if (file->f_flags & O_NONBLOCK) | 312 | if (file->f_flags & O_NONBLOCK) |
295 | return -EAGAIN; | 313 | return -EAGAIN; |
296 | if (down_interruptible(&data->sem)) | 314 | if (down_interruptible(&data->mutex)) |
297 | return -EINTR; | 315 | return -EINTR; |
298 | } | 316 | } |
299 | 317 | ||
300 | n = data->cpu_check; | 318 | n = data->cpu_check; |
301 | for (i = 0; i < NR_CPUS; i++) { | 319 | for (i = 0; i < NR_CPUS; i++) { |
302 | if (test_bit(n, &data->cpu_event) && cpu_online(n)) { | 320 | if (cpu_isset(n, data->cpu_event)) { |
321 | if (!cpu_online(n)) { | ||
322 | cpu_clear(n, data->cpu_event); | ||
323 | continue; | ||
324 | } | ||
303 | cpu = n; | 325 | cpu = n; |
304 | break; | 326 | break; |
305 | } | 327 | } |
@@ -310,9 +332,6 @@ retry: | |||
310 | if (cpu == -1) | 332 | if (cpu == -1) |
311 | goto retry; | 333 | goto retry; |
312 | 334 | ||
313 | /* events are sticky until the user says "clear" */ | ||
314 | up(&data->sem); | ||
315 | |||
316 | /* for next read, start checking at next CPU */ | 335 | /* for next read, start checking at next CPU */ |
317 | data->cpu_check = cpu; | 336 | data->cpu_check = cpu; |
318 | if (++data->cpu_check == NR_CPUS) | 337 | if (++data->cpu_check == NR_CPUS) |
@@ -381,10 +400,8 @@ salinfo_log_release(struct inode *inode, struct file *file) | |||
381 | static void | 400 | static void |
382 | call_on_cpu(int cpu, void (*fn)(void *), void *arg) | 401 | call_on_cpu(int cpu, void (*fn)(void *), void *arg) |
383 | { | 402 | { |
384 | cpumask_t save_cpus_allowed, new_cpus_allowed; | 403 | cpumask_t save_cpus_allowed = current->cpus_allowed; |
385 | memcpy(&save_cpus_allowed, ¤t->cpus_allowed, sizeof(save_cpus_allowed)); | 404 | cpumask_t new_cpus_allowed = cpumask_of_cpu(cpu); |
386 | memset(&new_cpus_allowed, 0, sizeof(new_cpus_allowed)); | ||
387 | set_bit(cpu, &new_cpus_allowed); | ||
388 | set_cpus_allowed(current, new_cpus_allowed); | 405 | set_cpus_allowed(current, new_cpus_allowed); |
389 | (*fn)(arg); | 406 | (*fn)(arg); |
390 | set_cpus_allowed(current, save_cpus_allowed); | 407 | set_cpus_allowed(current, save_cpus_allowed); |
@@ -433,10 +450,10 @@ retry: | |||
433 | if (!data->saved_num) | 450 | if (!data->saved_num) |
434 | call_on_cpu(cpu, salinfo_log_read_cpu, data); | 451 | call_on_cpu(cpu, salinfo_log_read_cpu, data); |
435 | if (!data->log_size) { | 452 | if (!data->log_size) { |
436 | data->state = STATE_NO_DATA; | 453 | data->state = STATE_NO_DATA; |
437 | clear_bit(cpu, &data->cpu_event); | 454 | cpu_clear(cpu, data->cpu_event); |
438 | } else { | 455 | } else { |
439 | data->state = STATE_LOG_RECORD; | 456 | data->state = STATE_LOG_RECORD; |
440 | } | 457 | } |
441 | } | 458 | } |
442 | 459 | ||
@@ -473,27 +490,31 @@ static int | |||
473 | salinfo_log_clear(struct salinfo_data *data, int cpu) | 490 | salinfo_log_clear(struct salinfo_data *data, int cpu) |
474 | { | 491 | { |
475 | sal_log_record_header_t *rh; | 492 | sal_log_record_header_t *rh; |
493 | unsigned long flags; | ||
494 | spin_lock_irqsave(&data_saved_lock, flags); | ||
476 | data->state = STATE_NO_DATA; | 495 | data->state = STATE_NO_DATA; |
477 | if (!test_bit(cpu, &data->cpu_event)) | 496 | if (!cpu_isset(cpu, data->cpu_event)) { |
497 | spin_unlock_irqrestore(&data_saved_lock, flags); | ||
478 | return 0; | 498 | return 0; |
479 | down(&data->sem); | 499 | } |
480 | clear_bit(cpu, &data->cpu_event); | 500 | cpu_clear(cpu, data->cpu_event); |
481 | if (data->saved_num) { | 501 | if (data->saved_num) { |
482 | unsigned long flags; | 502 | shift1_data_saved(data, data->saved_num - 1); |
483 | spin_lock_irqsave(&data_saved_lock, flags); | ||
484 | shift1_data_saved(data, data->saved_num - 1 ); | ||
485 | data->saved_num = 0; | 503 | data->saved_num = 0; |
486 | spin_unlock_irqrestore(&data_saved_lock, flags); | ||
487 | } | 504 | } |
505 | spin_unlock_irqrestore(&data_saved_lock, flags); | ||
488 | rh = (sal_log_record_header_t *)(data->log_buffer); | 506 | rh = (sal_log_record_header_t *)(data->log_buffer); |
489 | /* Corrected errors have already been cleared from SAL */ | 507 | /* Corrected errors have already been cleared from SAL */ |
490 | if (rh->severity != sal_log_severity_corrected) | 508 | if (rh->severity != sal_log_severity_corrected) |
491 | call_on_cpu(cpu, salinfo_log_clear_cpu, data); | 509 | call_on_cpu(cpu, salinfo_log_clear_cpu, data); |
492 | /* clearing a record may make a new record visible */ | 510 | /* clearing a record may make a new record visible */ |
493 | salinfo_log_new_read(cpu, data); | 511 | salinfo_log_new_read(cpu, data); |
494 | if (data->state == STATE_LOG_RECORD && | 512 | if (data->state == STATE_LOG_RECORD) { |
495 | !test_and_set_bit(cpu, &data->cpu_event)) | 513 | spin_lock_irqsave(&data_saved_lock, flags); |
496 | up(&data->sem); | 514 | cpu_set(cpu, data->cpu_event); |
515 | salinfo_work_to_do(data); | ||
516 | spin_unlock_irqrestore(&data_saved_lock, flags); | ||
517 | } | ||
497 | return 0; | 518 | return 0; |
498 | } | 519 | } |
499 | 520 | ||
@@ -550,6 +571,53 @@ static struct file_operations salinfo_data_fops = { | |||
550 | .write = salinfo_log_write, | 571 | .write = salinfo_log_write, |
551 | }; | 572 | }; |
552 | 573 | ||
574 | #ifdef CONFIG_HOTPLUG_CPU | ||
575 | static int __devinit | ||
576 | salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) | ||
577 | { | ||
578 | unsigned int i, cpu = (unsigned long)hcpu; | ||
579 | unsigned long flags; | ||
580 | struct salinfo_data *data; | ||
581 | switch (action) { | ||
582 | case CPU_ONLINE: | ||
583 | spin_lock_irqsave(&data_saved_lock, flags); | ||
584 | for (i = 0, data = salinfo_data; | ||
585 | i < ARRAY_SIZE(salinfo_data); | ||
586 | ++i, ++data) { | ||
587 | cpu_set(cpu, data->cpu_event); | ||
588 | salinfo_work_to_do(data); | ||
589 | } | ||
590 | spin_unlock_irqrestore(&data_saved_lock, flags); | ||
591 | break; | ||
592 | case CPU_DEAD: | ||
593 | spin_lock_irqsave(&data_saved_lock, flags); | ||
594 | for (i = 0, data = salinfo_data; | ||
595 | i < ARRAY_SIZE(salinfo_data); | ||
596 | ++i, ++data) { | ||
597 | struct salinfo_data_saved *data_saved; | ||
598 | int j; | ||
599 | for (j = ARRAY_SIZE(data->data_saved) - 1, data_saved = data->data_saved + j; | ||
600 | j >= 0; | ||
601 | --j, --data_saved) { | ||
602 | if (data_saved->buffer && data_saved->cpu == cpu) { | ||
603 | shift1_data_saved(data, j); | ||
604 | } | ||
605 | } | ||
606 | cpu_clear(cpu, data->cpu_event); | ||
607 | } | ||
608 | spin_unlock_irqrestore(&data_saved_lock, flags); | ||
609 | break; | ||
610 | } | ||
611 | return NOTIFY_OK; | ||
612 | } | ||
613 | |||
614 | static struct notifier_block salinfo_cpu_notifier = | ||
615 | { | ||
616 | .notifier_call = salinfo_cpu_callback, | ||
617 | .priority = 0, | ||
618 | }; | ||
619 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
620 | |||
553 | static int __init | 621 | static int __init |
554 | salinfo_init(void) | 622 | salinfo_init(void) |
555 | { | 623 | { |
@@ -557,7 +625,7 @@ salinfo_init(void) | |||
557 | struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */ | 625 | struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */ |
558 | struct proc_dir_entry *dir, *entry; | 626 | struct proc_dir_entry *dir, *entry; |
559 | struct salinfo_data *data; | 627 | struct salinfo_data *data; |
560 | int i, j, online; | 628 | int i, j; |
561 | 629 | ||
562 | salinfo_dir = proc_mkdir("sal", NULL); | 630 | salinfo_dir = proc_mkdir("sal", NULL); |
563 | if (!salinfo_dir) | 631 | if (!salinfo_dir) |
@@ -572,7 +640,7 @@ salinfo_init(void) | |||
572 | for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) { | 640 | for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) { |
573 | data = salinfo_data + i; | 641 | data = salinfo_data + i; |
574 | data->type = i; | 642 | data->type = i; |
575 | sema_init(&data->sem, 0); | 643 | init_MUTEX(&data->mutex); |
576 | dir = proc_mkdir(salinfo_log_name[i], salinfo_dir); | 644 | dir = proc_mkdir(salinfo_log_name[i], salinfo_dir); |
577 | if (!dir) | 645 | if (!dir) |
578 | continue; | 646 | continue; |
@@ -592,12 +660,8 @@ salinfo_init(void) | |||
592 | *sdir++ = entry; | 660 | *sdir++ = entry; |
593 | 661 | ||
594 | /* we missed any events before now */ | 662 | /* we missed any events before now */ |
595 | online = 0; | 663 | for_each_online_cpu(j) |
596 | for_each_online_cpu(j) { | 664 | cpu_set(j, data->cpu_event); |
597 | set_bit(j, &data->cpu_event); | ||
598 | ++online; | ||
599 | } | ||
600 | sema_init(&data->sem, online); | ||
601 | 665 | ||
602 | *sdir++ = dir; | 666 | *sdir++ = dir; |
603 | } | 667 | } |
@@ -609,6 +673,10 @@ salinfo_init(void) | |||
609 | salinfo_timer.function = &salinfo_timeout; | 673 | salinfo_timer.function = &salinfo_timeout; |
610 | add_timer(&salinfo_timer); | 674 | add_timer(&salinfo_timer); |
611 | 675 | ||
676 | #ifdef CONFIG_HOTPLUG_CPU | ||
677 | register_cpu_notifier(&salinfo_cpu_notifier); | ||
678 | #endif | ||
679 | |||
612 | return 0; | 680 | return 0; |
613 | } | 681 | } |
614 | 682 | ||
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index d3e0ecb56d62..55391901b013 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c | |||
@@ -530,12 +530,15 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, | |||
530 | if (fsys_mode(current, ®s)) { | 530 | if (fsys_mode(current, ®s)) { |
531 | extern char __kernel_syscall_via_break[]; | 531 | extern char __kernel_syscall_via_break[]; |
532 | /* | 532 | /* |
533 | * Got a trap in fsys-mode: Taken Branch Trap and Single Step trap | 533 | * Got a trap in fsys-mode: Taken Branch Trap |
534 | * need special handling; Debug trap is not supposed to happen. | 534 | * and Single Step trap need special handling; |
535 | * Debug trap is ignored (we disable it here | ||
536 | * and re-enable it in the lower-privilege trap). | ||
535 | */ | 537 | */ |
536 | if (unlikely(vector == 29)) { | 538 | if (unlikely(vector == 29)) { |
537 | die("Got debug trap in fsys-mode---not supposed to happen!", | 539 | set_thread_flag(TIF_DB_DISABLED); |
538 | ®s, 0); | 540 | ia64_psr(®s)->db = 0; |
541 | ia64_psr(®s)->lp = 1; | ||
539 | return; | 542 | return; |
540 | } | 543 | } |
541 | /* re-do the system call via break 0x100000: */ | 544 | /* re-do the system call via break 0x100000: */ |
@@ -589,10 +592,19 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, | |||
589 | case 34: | 592 | case 34: |
590 | if (isr & 0x2) { | 593 | if (isr & 0x2) { |
591 | /* Lower-Privilege Transfer Trap */ | 594 | /* Lower-Privilege Transfer Trap */ |
595 | |||
596 | /* If we disabled debug traps during an fsyscall, | ||
597 | * re-enable them here. | ||
598 | */ | ||
599 | if (test_thread_flag(TIF_DB_DISABLED)) { | ||
600 | clear_thread_flag(TIF_DB_DISABLED); | ||
601 | ia64_psr(®s)->db = 1; | ||
602 | } | ||
603 | |||
592 | /* | 604 | /* |
593 | * Just clear PSR.lp and then return immediately: all the | 605 | * Just clear PSR.lp and then return immediately: |
594 | * interesting work (e.g., signal delivery is done in the kernel | 606 | * all the interesting work (e.g., signal delivery) |
595 | * exit path). | 607 | * is done in the kernel exit path. |
596 | */ | 608 | */ |
597 | ia64_psr(®s)->lp = 0; | 609 | ia64_psr(®s)->lp = 0; |
598 | return; | 610 | return; |
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index 41105d454423..6a4eec9113e8 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c | |||
@@ -90,7 +90,7 @@ ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start, | |||
90 | { | 90 | { |
91 | static DEFINE_SPINLOCK(ptcg_lock); | 91 | static DEFINE_SPINLOCK(ptcg_lock); |
92 | 92 | ||
93 | if (mm != current->active_mm) { | 93 | if (mm != current->active_mm || !current->mm) { |
94 | flush_tlb_all(); | 94 | flush_tlb_all(); |
95 | return; | 95 | return; |
96 | } | 96 | } |
diff --git a/arch/ia64/sn/include/xtalk/hubdev.h b/arch/ia64/sn/include/xtalk/hubdev.h index 71c2b271b4c6..4d417c301201 100644 --- a/arch/ia64/sn/include/xtalk/hubdev.h +++ b/arch/ia64/sn/include/xtalk/hubdev.h | |||
@@ -26,11 +26,14 @@ | |||
26 | #define IIO_NUM_ITTES 7 | 26 | #define IIO_NUM_ITTES 7 |
27 | #define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1) | 27 | #define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1) |
28 | 28 | ||
29 | struct sn_flush_device_list { | 29 | /* This struct is shared between the PROM and the kernel. |
30 | * Changes to this struct will require corresponding changes to the kernel. | ||
31 | */ | ||
32 | struct sn_flush_device_common { | ||
30 | int sfdl_bus; | 33 | int sfdl_bus; |
31 | int sfdl_slot; | 34 | int sfdl_slot; |
32 | int sfdl_pin; | 35 | int sfdl_pin; |
33 | struct bar_list { | 36 | struct common_bar_list { |
34 | unsigned long start; | 37 | unsigned long start; |
35 | unsigned long end; | 38 | unsigned long end; |
36 | } sfdl_bar_list[6]; | 39 | } sfdl_bar_list[6]; |
@@ -40,14 +43,19 @@ struct sn_flush_device_list { | |||
40 | uint32_t sfdl_persistent_busnum; | 43 | uint32_t sfdl_persistent_busnum; |
41 | uint32_t sfdl_persistent_segment; | 44 | uint32_t sfdl_persistent_segment; |
42 | struct pcibus_info *sfdl_pcibus_info; | 45 | struct pcibus_info *sfdl_pcibus_info; |
46 | }; | ||
47 | |||
48 | /* This struct is kernel only and is not used by the PROM */ | ||
49 | struct sn_flush_device_kernel { | ||
43 | spinlock_t sfdl_flush_lock; | 50 | spinlock_t sfdl_flush_lock; |
51 | struct sn_flush_device_common *common; | ||
44 | }; | 52 | }; |
45 | 53 | ||
46 | /* | 54 | /* |
47 | * **widget_p - Used as an array[wid_num][device] of sn_flush_device_list. | 55 | * **widget_p - Used as an array[wid_num][device] of sn_flush_device_kernel. |
48 | */ | 56 | */ |
49 | struct sn_flush_nasid_entry { | 57 | struct sn_flush_nasid_entry { |
50 | struct sn_flush_device_list **widget_p; /* Used as a array of wid_num */ | 58 | struct sn_flush_device_kernel **widget_p; // Used as an array of wid_num |
51 | uint64_t iio_itte[8]; | 59 | uint64_t iio_itte[8]; |
52 | }; | 60 | }; |
53 | 61 | ||
diff --git a/arch/ia64/sn/kernel/bte_error.c b/arch/ia64/sn/kernel/bte_error.c index fcbc748ae433..f1ec1370b3e3 100644 --- a/arch/ia64/sn/kernel/bte_error.c +++ b/arch/ia64/sn/kernel/bte_error.c | |||
@@ -33,7 +33,7 @@ void bte_error_handler(unsigned long); | |||
33 | * Wait until all BTE related CRBs are completed | 33 | * Wait until all BTE related CRBs are completed |
34 | * and then reset the interfaces. | 34 | * and then reset the interfaces. |
35 | */ | 35 | */ |
36 | void shub1_bte_error_handler(unsigned long _nodepda) | 36 | int shub1_bte_error_handler(unsigned long _nodepda) |
37 | { | 37 | { |
38 | struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; | 38 | struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; |
39 | struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer; | 39 | struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer; |
@@ -53,7 +53,7 @@ void shub1_bte_error_handler(unsigned long _nodepda) | |||
53 | (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) { | 53 | (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) { |
54 | BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda, | 54 | BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda, |
55 | smp_processor_id())); | 55 | smp_processor_id())); |
56 | return; | 56 | return 1; |
57 | } | 57 | } |
58 | 58 | ||
59 | /* Determine information about our hub */ | 59 | /* Determine information about our hub */ |
@@ -81,7 +81,7 @@ void shub1_bte_error_handler(unsigned long _nodepda) | |||
81 | mod_timer(recovery_timer, HZ * 5); | 81 | mod_timer(recovery_timer, HZ * 5); |
82 | BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda, | 82 | BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda, |
83 | smp_processor_id())); | 83 | smp_processor_id())); |
84 | return; | 84 | return 1; |
85 | } | 85 | } |
86 | if (icmr.ii_icmr_fld_s.i_crb_vld != 0) { | 86 | if (icmr.ii_icmr_fld_s.i_crb_vld != 0) { |
87 | 87 | ||
@@ -99,7 +99,7 @@ void shub1_bte_error_handler(unsigned long _nodepda) | |||
99 | BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n", | 99 | BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n", |
100 | err_nodepda, smp_processor_id(), | 100 | err_nodepda, smp_processor_id(), |
101 | i)); | 101 | i)); |
102 | return; | 102 | return 1; |
103 | } | 103 | } |
104 | } | 104 | } |
105 | } | 105 | } |
@@ -124,6 +124,42 @@ void shub1_bte_error_handler(unsigned long _nodepda) | |||
124 | REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval); | 124 | REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval); |
125 | 125 | ||
126 | del_timer(recovery_timer); | 126 | del_timer(recovery_timer); |
127 | return 0; | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * Wait until all BTE related CRBs are completed | ||
132 | * and then reset the interfaces. | ||
133 | */ | ||
134 | int shub2_bte_error_handler(unsigned long _nodepda) | ||
135 | { | ||
136 | struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; | ||
137 | struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer; | ||
138 | struct bteinfo_s *bte; | ||
139 | nasid_t nasid; | ||
140 | u64 status; | ||
141 | int i; | ||
142 | |||
143 | nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode); | ||
144 | |||
145 | /* | ||
146 | * Verify that all the BTEs are complete | ||
147 | */ | ||
148 | for (i = 0; i < BTES_PER_NODE; i++) { | ||
149 | bte = &err_nodepda->bte_if[i]; | ||
150 | status = BTE_LNSTAT_LOAD(bte); | ||
151 | if ((status & IBLS_ERROR) || !(status & IBLS_BUSY)) | ||
152 | continue; | ||
153 | mod_timer(recovery_timer, HZ * 5); | ||
154 | BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda, | ||
155 | smp_processor_id())); | ||
156 | return 1; | ||
157 | } | ||
158 | if (ia64_sn_bte_recovery(nasid)) | ||
159 | panic("bte_error_handler(): Fatal BTE Error"); | ||
160 | |||
161 | del_timer(recovery_timer); | ||
162 | return 0; | ||
127 | } | 163 | } |
128 | 164 | ||
129 | /* | 165 | /* |
@@ -135,7 +171,6 @@ void bte_error_handler(unsigned long _nodepda) | |||
135 | struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; | 171 | struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; |
136 | spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock; | 172 | spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock; |
137 | int i; | 173 | int i; |
138 | nasid_t nasid; | ||
139 | unsigned long irq_flags; | 174 | unsigned long irq_flags; |
140 | volatile u64 *notify; | 175 | volatile u64 *notify; |
141 | bte_result_t bh_error; | 176 | bte_result_t bh_error; |
@@ -160,12 +195,15 @@ void bte_error_handler(unsigned long _nodepda) | |||
160 | } | 195 | } |
161 | 196 | ||
162 | if (is_shub1()) { | 197 | if (is_shub1()) { |
163 | shub1_bte_error_handler(_nodepda); | 198 | if (shub1_bte_error_handler(_nodepda)) { |
199 | spin_unlock_irqrestore(recovery_lock, irq_flags); | ||
200 | return; | ||
201 | } | ||
164 | } else { | 202 | } else { |
165 | nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode); | 203 | if (shub2_bte_error_handler(_nodepda)) { |
166 | 204 | spin_unlock_irqrestore(recovery_lock, irq_flags); | |
167 | if (ia64_sn_bte_recovery(nasid)) | 205 | return; |
168 | panic("bte_error_handler(): Fatal BTE Error"); | 206 | } |
169 | } | 207 | } |
170 | 208 | ||
171 | for (i = 0; i < BTES_PER_NODE; i++) { | 209 | for (i = 0; i < BTES_PER_NODE; i++) { |
diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c index 5c5eb01c50f0..56ab6bae00ee 100644 --- a/arch/ia64/sn/kernel/huberror.c +++ b/arch/ia64/sn/kernel/huberror.c | |||
@@ -32,13 +32,14 @@ static irqreturn_t hub_eint_handler(int irq, void *arg, struct pt_regs *ep) | |||
32 | ret_stuff.v0 = 0; | 32 | ret_stuff.v0 = 0; |
33 | hubdev_info = (struct hubdev_info *)arg; | 33 | hubdev_info = (struct hubdev_info *)arg; |
34 | nasid = hubdev_info->hdi_nasid; | 34 | nasid = hubdev_info->hdi_nasid; |
35 | SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT, | 35 | |
36 | if (is_shub1()) { | ||
37 | SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT, | ||
36 | (u64) nasid, 0, 0, 0, 0, 0, 0); | 38 | (u64) nasid, 0, 0, 0, 0, 0, 0); |
37 | 39 | ||
38 | if ((int)ret_stuff.v0) | 40 | if ((int)ret_stuff.v0) |
39 | panic("hubii_eint_handler(): Fatal TIO Error"); | 41 | panic("hubii_eint_handler(): Fatal TIO Error"); |
40 | 42 | ||
41 | if (is_shub1()) { | ||
42 | if (!(nasid & 1)) /* Not a TIO, handle CRB errors */ | 43 | if (!(nasid & 1)) /* Not a TIO, handle CRB errors */ |
43 | (void)hubiio_crb_error_handler(hubdev_info); | 44 | (void)hubiio_crb_error_handler(hubdev_info); |
44 | } else | 45 | } else |
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 318087e35b66..258d9d7aff98 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c | |||
@@ -76,11 +76,12 @@ static struct sn_pcibus_provider sn_pci_default_provider = { | |||
76 | }; | 76 | }; |
77 | 77 | ||
78 | /* | 78 | /* |
79 | * Retrieve the DMA Flush List given nasid. This list is needed | 79 | * Retrieve the DMA Flush List given nasid, widget, and device. |
80 | * to implement the WAR - Flush DMA data on PIO Reads. | 80 | * This list is needed to implement the WAR - Flush DMA data on PIO Reads. |
81 | */ | 81 | */ |
82 | static inline uint64_t | 82 | static inline u64 |
83 | sal_get_widget_dmaflush_list(u64 nasid, u64 widget_num, u64 address) | 83 | sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num, |
84 | u64 address) | ||
84 | { | 85 | { |
85 | 86 | ||
86 | struct ia64_sal_retval ret_stuff; | 87 | struct ia64_sal_retval ret_stuff; |
@@ -88,17 +89,17 @@ sal_get_widget_dmaflush_list(u64 nasid, u64 widget_num, u64 address) | |||
88 | ret_stuff.v0 = 0; | 89 | ret_stuff.v0 = 0; |
89 | 90 | ||
90 | SAL_CALL_NOLOCK(ret_stuff, | 91 | SAL_CALL_NOLOCK(ret_stuff, |
91 | (u64) SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST, | 92 | (u64) SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST, |
92 | (u64) nasid, (u64) widget_num, (u64) address, 0, 0, 0, | 93 | (u64) nasid, (u64) widget_num, |
93 | 0); | 94 | (u64) device_num, (u64) address, 0, 0, 0); |
94 | return ret_stuff.v0; | 95 | return ret_stuff.status; |
95 | 96 | ||
96 | } | 97 | } |
97 | 98 | ||
98 | /* | 99 | /* |
99 | * Retrieve the hub device info structure for the given nasid. | 100 | * Retrieve the hub device info structure for the given nasid. |
100 | */ | 101 | */ |
101 | static inline uint64_t sal_get_hubdev_info(u64 handle, u64 address) | 102 | static inline u64 sal_get_hubdev_info(u64 handle, u64 address) |
102 | { | 103 | { |
103 | 104 | ||
104 | struct ia64_sal_retval ret_stuff; | 105 | struct ia64_sal_retval ret_stuff; |
@@ -114,7 +115,7 @@ static inline uint64_t sal_get_hubdev_info(u64 handle, u64 address) | |||
114 | /* | 115 | /* |
115 | * Retrieve the pci bus information given the bus number. | 116 | * Retrieve the pci bus information given the bus number. |
116 | */ | 117 | */ |
117 | static inline uint64_t sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) | 118 | static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) |
118 | { | 119 | { |
119 | 120 | ||
120 | struct ia64_sal_retval ret_stuff; | 121 | struct ia64_sal_retval ret_stuff; |
@@ -130,7 +131,7 @@ static inline uint64_t sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) | |||
130 | /* | 131 | /* |
131 | * Retrieve the pci device information given the bus and device|function number. | 132 | * Retrieve the pci device information given the bus and device|function number. |
132 | */ | 133 | */ |
133 | static inline uint64_t | 134 | static inline u64 |
134 | sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, | 135 | sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, |
135 | u64 sn_irq_info) | 136 | u64 sn_irq_info) |
136 | { | 137 | { |
@@ -170,12 +171,12 @@ sn_pcidev_info_get(struct pci_dev *dev) | |||
170 | */ | 171 | */ |
171 | static void sn_fixup_ionodes(void) | 172 | static void sn_fixup_ionodes(void) |
172 | { | 173 | { |
173 | 174 | struct sn_flush_device_kernel *sn_flush_device_kernel; | |
174 | struct sn_flush_device_list *sn_flush_device_list; | 175 | struct sn_flush_device_kernel *dev_entry; |
175 | struct hubdev_info *hubdev; | 176 | struct hubdev_info *hubdev; |
176 | uint64_t status; | 177 | u64 status; |
177 | uint64_t nasid; | 178 | u64 nasid; |
178 | int i, widget; | 179 | int i, widget, device; |
179 | 180 | ||
180 | /* | 181 | /* |
181 | * Get SGI Specific HUB chipset information. | 182 | * Get SGI Specific HUB chipset information. |
@@ -186,7 +187,7 @@ static void sn_fixup_ionodes(void) | |||
186 | nasid = cnodeid_to_nasid(i); | 187 | nasid = cnodeid_to_nasid(i); |
187 | hubdev->max_segment_number = 0xffffffff; | 188 | hubdev->max_segment_number = 0xffffffff; |
188 | hubdev->max_pcibus_number = 0xff; | 189 | hubdev->max_pcibus_number = 0xff; |
189 | status = sal_get_hubdev_info(nasid, (uint64_t) __pa(hubdev)); | 190 | status = sal_get_hubdev_info(nasid, (u64) __pa(hubdev)); |
190 | if (status) | 191 | if (status) |
191 | continue; | 192 | continue; |
192 | 193 | ||
@@ -213,38 +214,49 @@ static void sn_fixup_ionodes(void) | |||
213 | 214 | ||
214 | hubdev->hdi_flush_nasid_list.widget_p = | 215 | hubdev->hdi_flush_nasid_list.widget_p = |
215 | kmalloc((HUB_WIDGET_ID_MAX + 1) * | 216 | kmalloc((HUB_WIDGET_ID_MAX + 1) * |
216 | sizeof(struct sn_flush_device_list *), GFP_KERNEL); | 217 | sizeof(struct sn_flush_device_kernel *), |
217 | 218 | GFP_KERNEL); | |
218 | memset(hubdev->hdi_flush_nasid_list.widget_p, 0x0, | 219 | memset(hubdev->hdi_flush_nasid_list.widget_p, 0x0, |
219 | (HUB_WIDGET_ID_MAX + 1) * | 220 | (HUB_WIDGET_ID_MAX + 1) * |
220 | sizeof(struct sn_flush_device_list *)); | 221 | sizeof(struct sn_flush_device_kernel *)); |
221 | 222 | ||
222 | for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) { | 223 | for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) { |
223 | sn_flush_device_list = kmalloc(DEV_PER_WIDGET * | 224 | sn_flush_device_kernel = kmalloc(DEV_PER_WIDGET * |
224 | sizeof(struct | 225 | sizeof(struct |
225 | sn_flush_device_list), | 226 | sn_flush_device_kernel), |
226 | GFP_KERNEL); | 227 | GFP_KERNEL); |
227 | memset(sn_flush_device_list, 0x0, | 228 | if (!sn_flush_device_kernel) |
229 | BUG(); | ||
230 | memset(sn_flush_device_kernel, 0x0, | ||
228 | DEV_PER_WIDGET * | 231 | DEV_PER_WIDGET * |
229 | sizeof(struct sn_flush_device_list)); | 232 | sizeof(struct sn_flush_device_kernel)); |
230 | 233 | ||
231 | status = | 234 | dev_entry = sn_flush_device_kernel; |
232 | sal_get_widget_dmaflush_list(nasid, widget, | 235 | for (device = 0; device < DEV_PER_WIDGET; |
233 | (uint64_t) | 236 | device++,dev_entry++) { |
234 | __pa | 237 | dev_entry->common = kmalloc(sizeof(struct |
235 | (sn_flush_device_list)); | 238 | sn_flush_device_common), |
236 | if (status) { | 239 | GFP_KERNEL); |
237 | kfree(sn_flush_device_list); | 240 | if (!dev_entry->common) |
238 | continue; | 241 | BUG(); |
242 | memset(dev_entry->common, 0x0, sizeof(struct | ||
243 | sn_flush_device_common)); | ||
244 | |||
245 | status = sal_get_device_dmaflush_list(nasid, | ||
246 | widget, | ||
247 | device, | ||
248 | (u64)(dev_entry->common)); | ||
249 | if (status) | ||
250 | BUG(); | ||
251 | |||
252 | spin_lock_init(&dev_entry->sfdl_flush_lock); | ||
239 | } | 253 | } |
240 | 254 | ||
241 | spin_lock_init(&sn_flush_device_list->sfdl_flush_lock); | 255 | if (sn_flush_device_kernel) |
242 | hubdev->hdi_flush_nasid_list.widget_p[widget] = | 256 | hubdev->hdi_flush_nasid_list.widget_p[widget] = |
243 | sn_flush_device_list; | 257 | sn_flush_device_kernel; |
244 | } | 258 | } |
245 | |||
246 | } | 259 | } |
247 | |||
248 | } | 260 | } |
249 | 261 | ||
250 | /* | 262 | /* |
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c index abf4fc2a87bb..0c0a68902409 100644 --- a/arch/ia64/sn/kernel/xpc_channel.c +++ b/arch/ia64/sn/kernel/xpc_channel.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. | 6 | * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | 9 | ||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <asm/sn/bte.h> | 25 | #include <asm/sn/bte.h> |
26 | #include <asm/sn/sn_sal.h> | 26 | #include <asm/sn/sn_sal.h> |
27 | #include "xpc.h" | 27 | #include <asm/sn/xpc.h> |
28 | 28 | ||
29 | 29 | ||
30 | /* | 30 | /* |
@@ -779,6 +779,12 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) | |||
779 | 779 | ||
780 | /* both sides are disconnected now */ | 780 | /* both sides are disconnected now */ |
781 | 781 | ||
782 | if (ch->flags & XPC_C_CONNECTCALLOUT) { | ||
783 | spin_unlock_irqrestore(&ch->lock, *irq_flags); | ||
784 | xpc_disconnect_callout(ch, xpcDisconnected); | ||
785 | spin_lock_irqsave(&ch->lock, *irq_flags); | ||
786 | } | ||
787 | |||
782 | /* it's now safe to free the channel's message queues */ | 788 | /* it's now safe to free the channel's message queues */ |
783 | xpc_free_msgqueues(ch); | 789 | xpc_free_msgqueues(ch); |
784 | 790 | ||
@@ -1645,7 +1651,7 @@ xpc_disconnect_channel(const int line, struct xpc_channel *ch, | |||
1645 | 1651 | ||
1646 | 1652 | ||
1647 | void | 1653 | void |
1648 | xpc_disconnecting_callout(struct xpc_channel *ch) | 1654 | xpc_disconnect_callout(struct xpc_channel *ch, enum xpc_retval reason) |
1649 | { | 1655 | { |
1650 | /* | 1656 | /* |
1651 | * Let the channel's registerer know that the channel is being | 1657 | * Let the channel's registerer know that the channel is being |
@@ -1654,15 +1660,13 @@ xpc_disconnecting_callout(struct xpc_channel *ch) | |||
1654 | */ | 1660 | */ |
1655 | 1661 | ||
1656 | if (ch->func != NULL) { | 1662 | if (ch->func != NULL) { |
1657 | dev_dbg(xpc_chan, "ch->func() called, reason=xpcDisconnecting," | 1663 | dev_dbg(xpc_chan, "ch->func() called, reason=%d, partid=%d, " |
1658 | " partid=%d, channel=%d\n", ch->partid, ch->number); | 1664 | "channel=%d\n", reason, ch->partid, ch->number); |
1659 | 1665 | ||
1660 | ch->func(xpcDisconnecting, ch->partid, ch->number, NULL, | 1666 | ch->func(reason, ch->partid, ch->number, NULL, ch->key); |
1661 | ch->key); | ||
1662 | 1667 | ||
1663 | dev_dbg(xpc_chan, "ch->func() returned, reason=" | 1668 | dev_dbg(xpc_chan, "ch->func() returned, reason=%d, partid=%d, " |
1664 | "xpcDisconnecting, partid=%d, channel=%d\n", | 1669 | "channel=%d\n", reason, ch->partid, ch->number); |
1665 | ch->partid, ch->number); | ||
1666 | } | 1670 | } |
1667 | } | 1671 | } |
1668 | 1672 | ||
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index b617236524c6..8930586e0eb4 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. | 6 | * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | 9 | ||
@@ -59,7 +59,7 @@ | |||
59 | #include <asm/sn/sn_sal.h> | 59 | #include <asm/sn/sn_sal.h> |
60 | #include <asm/kdebug.h> | 60 | #include <asm/kdebug.h> |
61 | #include <asm/uaccess.h> | 61 | #include <asm/uaccess.h> |
62 | #include "xpc.h" | 62 | #include <asm/sn/xpc.h> |
63 | 63 | ||
64 | 64 | ||
65 | /* define two XPC debug device structures to be used with dev_dbg() et al */ | 65 | /* define two XPC debug device structures to be used with dev_dbg() et al */ |
@@ -82,6 +82,9 @@ struct device *xpc_part = &xpc_part_dbg_subname; | |||
82 | struct device *xpc_chan = &xpc_chan_dbg_subname; | 82 | struct device *xpc_chan = &xpc_chan_dbg_subname; |
83 | 83 | ||
84 | 84 | ||
85 | static int xpc_kdebug_ignore; | ||
86 | |||
87 | |||
85 | /* systune related variables for /proc/sys directories */ | 88 | /* systune related variables for /proc/sys directories */ |
86 | 89 | ||
87 | static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL; | 90 | static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL; |
@@ -162,6 +165,8 @@ static ctl_table xpc_sys_dir[] = { | |||
162 | }; | 165 | }; |
163 | static struct ctl_table_header *xpc_sysctl; | 166 | static struct ctl_table_header *xpc_sysctl; |
164 | 167 | ||
168 | /* non-zero if any remote partition disengage request was timed out */ | ||
169 | int xpc_disengage_request_timedout; | ||
165 | 170 | ||
166 | /* #of IRQs received */ | 171 | /* #of IRQs received */ |
167 | static atomic_t xpc_act_IRQ_rcvd; | 172 | static atomic_t xpc_act_IRQ_rcvd; |
@@ -773,7 +778,7 @@ xpc_daemonize_kthread(void *args) | |||
773 | ch->flags |= XPC_C_DISCONNECTCALLOUT; | 778 | ch->flags |= XPC_C_DISCONNECTCALLOUT; |
774 | spin_unlock_irqrestore(&ch->lock, irq_flags); | 779 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
775 | 780 | ||
776 | xpc_disconnecting_callout(ch); | 781 | xpc_disconnect_callout(ch, xpcDisconnecting); |
777 | } else { | 782 | } else { |
778 | spin_unlock_irqrestore(&ch->lock, irq_flags); | 783 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
779 | } | 784 | } |
@@ -921,9 +926,9 @@ static void | |||
921 | xpc_do_exit(enum xpc_retval reason) | 926 | xpc_do_exit(enum xpc_retval reason) |
922 | { | 927 | { |
923 | partid_t partid; | 928 | partid_t partid; |
924 | int active_part_count; | 929 | int active_part_count, printed_waiting_msg = 0; |
925 | struct xpc_partition *part; | 930 | struct xpc_partition *part; |
926 | unsigned long printmsg_time; | 931 | unsigned long printmsg_time, disengage_request_timeout = 0; |
927 | 932 | ||
928 | 933 | ||
929 | /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */ | 934 | /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */ |
@@ -953,7 +958,8 @@ xpc_do_exit(enum xpc_retval reason) | |||
953 | 958 | ||
954 | /* wait for all partitions to become inactive */ | 959 | /* wait for all partitions to become inactive */ |
955 | 960 | ||
956 | printmsg_time = jiffies; | 961 | printmsg_time = jiffies + (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ); |
962 | xpc_disengage_request_timedout = 0; | ||
957 | 963 | ||
958 | do { | 964 | do { |
959 | active_part_count = 0; | 965 | active_part_count = 0; |
@@ -969,20 +975,39 @@ xpc_do_exit(enum xpc_retval reason) | |||
969 | active_part_count++; | 975 | active_part_count++; |
970 | 976 | ||
971 | XPC_DEACTIVATE_PARTITION(part, reason); | 977 | XPC_DEACTIVATE_PARTITION(part, reason); |
972 | } | ||
973 | 978 | ||
974 | if (active_part_count == 0) { | 979 | if (part->disengage_request_timeout > |
975 | break; | 980 | disengage_request_timeout) { |
981 | disengage_request_timeout = | ||
982 | part->disengage_request_timeout; | ||
983 | } | ||
976 | } | 984 | } |
977 | 985 | ||
978 | if (jiffies >= printmsg_time) { | 986 | if (xpc_partition_engaged(-1UL)) { |
979 | dev_info(xpc_part, "waiting for partitions to " | 987 | if (time_after(jiffies, printmsg_time)) { |
980 | "deactivate/disengage, active count=%d, remote " | 988 | dev_info(xpc_part, "waiting for remote " |
981 | "engaged=0x%lx\n", active_part_count, | 989 | "partitions to disengage, timeout in " |
982 | xpc_partition_engaged(1UL << partid)); | 990 | "%ld seconds\n", |
983 | 991 | (disengage_request_timeout - jiffies) | |
984 | printmsg_time = jiffies + | 992 | / HZ); |
993 | printmsg_time = jiffies + | ||
985 | (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ); | 994 | (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ); |
995 | printed_waiting_msg = 1; | ||
996 | } | ||
997 | |||
998 | } else if (active_part_count > 0) { | ||
999 | if (printed_waiting_msg) { | ||
1000 | dev_info(xpc_part, "waiting for local partition" | ||
1001 | " to disengage\n"); | ||
1002 | printed_waiting_msg = 0; | ||
1003 | } | ||
1004 | |||
1005 | } else { | ||
1006 | if (!xpc_disengage_request_timedout) { | ||
1007 | dev_info(xpc_part, "all partitions have " | ||
1008 | "disengaged\n"); | ||
1009 | } | ||
1010 | break; | ||
986 | } | 1011 | } |
987 | 1012 | ||
988 | /* sleep for a 1/3 of a second or so */ | 1013 | /* sleep for a 1/3 of a second or so */ |
@@ -1000,11 +1025,13 @@ xpc_do_exit(enum xpc_retval reason) | |||
1000 | del_timer_sync(&xpc_hb_timer); | 1025 | del_timer_sync(&xpc_hb_timer); |
1001 | DBUG_ON(xpc_vars->heartbeating_to_mask != 0); | 1026 | DBUG_ON(xpc_vars->heartbeating_to_mask != 0); |
1002 | 1027 | ||
1003 | /* take ourselves off of the reboot_notifier_list */ | 1028 | if (reason == xpcUnloading) { |
1004 | (void) unregister_reboot_notifier(&xpc_reboot_notifier); | 1029 | /* take ourselves off of the reboot_notifier_list */ |
1030 | (void) unregister_reboot_notifier(&xpc_reboot_notifier); | ||
1005 | 1031 | ||
1006 | /* take ourselves off of the die_notifier list */ | 1032 | /* take ourselves off of the die_notifier list */ |
1007 | (void) unregister_die_notifier(&xpc_die_notifier); | 1033 | (void) unregister_die_notifier(&xpc_die_notifier); |
1034 | } | ||
1008 | 1035 | ||
1009 | /* close down protections for IPI operations */ | 1036 | /* close down protections for IPI operations */ |
1010 | xpc_restrict_IPI_ops(); | 1037 | xpc_restrict_IPI_ops(); |
@@ -1020,7 +1047,35 @@ xpc_do_exit(enum xpc_retval reason) | |||
1020 | 1047 | ||
1021 | 1048 | ||
1022 | /* | 1049 | /* |
1023 | * Called when the system is about to be either restarted or halted. | 1050 | * This function is called when the system is being rebooted. |
1051 | */ | ||
1052 | static int | ||
1053 | xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) | ||
1054 | { | ||
1055 | enum xpc_retval reason; | ||
1056 | |||
1057 | |||
1058 | switch (event) { | ||
1059 | case SYS_RESTART: | ||
1060 | reason = xpcSystemReboot; | ||
1061 | break; | ||
1062 | case SYS_HALT: | ||
1063 | reason = xpcSystemHalt; | ||
1064 | break; | ||
1065 | case SYS_POWER_OFF: | ||
1066 | reason = xpcSystemPoweroff; | ||
1067 | break; | ||
1068 | default: | ||
1069 | reason = xpcSystemGoingDown; | ||
1070 | } | ||
1071 | |||
1072 | xpc_do_exit(reason); | ||
1073 | return NOTIFY_DONE; | ||
1074 | } | ||
1075 | |||
1076 | |||
1077 | /* | ||
1078 | * Notify other partitions to disengage from all references to our memory. | ||
1024 | */ | 1079 | */ |
1025 | static void | 1080 | static void |
1026 | xpc_die_disengage(void) | 1081 | xpc_die_disengage(void) |
@@ -1028,7 +1083,7 @@ xpc_die_disengage(void) | |||
1028 | struct xpc_partition *part; | 1083 | struct xpc_partition *part; |
1029 | partid_t partid; | 1084 | partid_t partid; |
1030 | unsigned long engaged; | 1085 | unsigned long engaged; |
1031 | long time, print_time, disengage_request_timeout; | 1086 | long time, printmsg_time, disengage_request_timeout; |
1032 | 1087 | ||
1033 | 1088 | ||
1034 | /* keep xpc_hb_checker thread from doing anything (just in case) */ | 1089 | /* keep xpc_hb_checker thread from doing anything (just in case) */ |
@@ -1055,57 +1110,53 @@ xpc_die_disengage(void) | |||
1055 | } | 1110 | } |
1056 | } | 1111 | } |
1057 | 1112 | ||
1058 | print_time = rtc_time(); | 1113 | time = rtc_time(); |
1059 | disengage_request_timeout = print_time + | 1114 | printmsg_time = time + |
1115 | (XPC_DISENGAGE_PRINTMSG_INTERVAL * sn_rtc_cycles_per_second); | ||
1116 | disengage_request_timeout = time + | ||
1060 | (xpc_disengage_request_timelimit * sn_rtc_cycles_per_second); | 1117 | (xpc_disengage_request_timelimit * sn_rtc_cycles_per_second); |
1061 | 1118 | ||
1062 | /* wait for all other partitions to disengage from us */ | 1119 | /* wait for all other partitions to disengage from us */ |
1063 | 1120 | ||
1064 | while ((engaged = xpc_partition_engaged(-1UL)) && | 1121 | while (1) { |
1065 | (time = rtc_time()) < disengage_request_timeout) { | 1122 | engaged = xpc_partition_engaged(-1UL); |
1123 | if (!engaged) { | ||
1124 | dev_info(xpc_part, "all partitions have disengaged\n"); | ||
1125 | break; | ||
1126 | } | ||
1066 | 1127 | ||
1067 | if (time >= print_time) { | 1128 | time = rtc_time(); |
1129 | if (time >= disengage_request_timeout) { | ||
1130 | for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) { | ||
1131 | if (engaged & (1UL << partid)) { | ||
1132 | dev_info(xpc_part, "disengage from " | ||
1133 | "remote partition %d timed " | ||
1134 | "out\n", partid); | ||
1135 | } | ||
1136 | } | ||
1137 | break; | ||
1138 | } | ||
1139 | |||
1140 | if (time >= printmsg_time) { | ||
1068 | dev_info(xpc_part, "waiting for remote partitions to " | 1141 | dev_info(xpc_part, "waiting for remote partitions to " |
1069 | "disengage, engaged=0x%lx\n", engaged); | 1142 | "disengage, timeout in %ld seconds\n", |
1070 | print_time = time + (XPC_DISENGAGE_PRINTMSG_INTERVAL * | 1143 | (disengage_request_timeout - time) / |
1144 | sn_rtc_cycles_per_second); | ||
1145 | printmsg_time = time + | ||
1146 | (XPC_DISENGAGE_PRINTMSG_INTERVAL * | ||
1071 | sn_rtc_cycles_per_second); | 1147 | sn_rtc_cycles_per_second); |
1072 | } | 1148 | } |
1073 | } | 1149 | } |
1074 | dev_info(xpc_part, "finished waiting for remote partitions to " | ||
1075 | "disengage, engaged=0x%lx\n", engaged); | ||
1076 | } | ||
1077 | |||
1078 | |||
1079 | /* | ||
1080 | * This function is called when the system is being rebooted. | ||
1081 | */ | ||
1082 | static int | ||
1083 | xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) | ||
1084 | { | ||
1085 | enum xpc_retval reason; | ||
1086 | |||
1087 | |||
1088 | switch (event) { | ||
1089 | case SYS_RESTART: | ||
1090 | reason = xpcSystemReboot; | ||
1091 | break; | ||
1092 | case SYS_HALT: | ||
1093 | reason = xpcSystemHalt; | ||
1094 | break; | ||
1095 | case SYS_POWER_OFF: | ||
1096 | reason = xpcSystemPoweroff; | ||
1097 | break; | ||
1098 | default: | ||
1099 | reason = xpcSystemGoingDown; | ||
1100 | } | ||
1101 | |||
1102 | xpc_do_exit(reason); | ||
1103 | return NOTIFY_DONE; | ||
1104 | } | 1150 | } |
1105 | 1151 | ||
1106 | 1152 | ||
1107 | /* | 1153 | /* |
1108 | * This function is called when the system is being rebooted. | 1154 | * This function is called when the system is being restarted or halted due |
1155 | * to some sort of system failure. If this is the case we need to notify the | ||
1156 | * other partitions to disengage from all references to our memory. | ||
1157 | * This function can also be called when our heartbeater could be offlined | ||
1158 | * for a time. In this case we need to notify other partitions to not worry | ||
1159 | * about the lack of a heartbeat. | ||
1109 | */ | 1160 | */ |
1110 | static int | 1161 | static int |
1111 | xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) | 1162 | xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) |
@@ -1115,11 +1166,25 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) | |||
1115 | case DIE_MACHINE_HALT: | 1166 | case DIE_MACHINE_HALT: |
1116 | xpc_die_disengage(); | 1167 | xpc_die_disengage(); |
1117 | break; | 1168 | break; |
1169 | |||
1170 | case DIE_KDEBUG_ENTER: | ||
1171 | /* Should lack of heartbeat be ignored by other partitions? */ | ||
1172 | if (!xpc_kdebug_ignore) { | ||
1173 | break; | ||
1174 | } | ||
1175 | /* fall through */ | ||
1118 | case DIE_MCA_MONARCH_ENTER: | 1176 | case DIE_MCA_MONARCH_ENTER: |
1119 | case DIE_INIT_MONARCH_ENTER: | 1177 | case DIE_INIT_MONARCH_ENTER: |
1120 | xpc_vars->heartbeat++; | 1178 | xpc_vars->heartbeat++; |
1121 | xpc_vars->heartbeat_offline = 1; | 1179 | xpc_vars->heartbeat_offline = 1; |
1122 | break; | 1180 | break; |
1181 | |||
1182 | case DIE_KDEBUG_LEAVE: | ||
1183 | /* Is lack of heartbeat being ignored by other partitions? */ | ||
1184 | if (!xpc_kdebug_ignore) { | ||
1185 | break; | ||
1186 | } | ||
1187 | /* fall through */ | ||
1123 | case DIE_MCA_MONARCH_LEAVE: | 1188 | case DIE_MCA_MONARCH_LEAVE: |
1124 | case DIE_INIT_MONARCH_LEAVE: | 1189 | case DIE_INIT_MONARCH_LEAVE: |
1125 | xpc_vars->heartbeat++; | 1190 | xpc_vars->heartbeat++; |
@@ -1344,3 +1409,7 @@ module_param(xpc_disengage_request_timelimit, int, 0); | |||
1344 | MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait " | 1409 | MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait " |
1345 | "for disengage request to complete."); | 1410 | "for disengage request to complete."); |
1346 | 1411 | ||
1412 | module_param(xpc_kdebug_ignore, int, 0); | ||
1413 | MODULE_PARM_DESC(xpc_kdebug_ignore, "Should lack of heartbeat be ignored by " | ||
1414 | "other partitions when dropping into kdebug."); | ||
1415 | |||
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c index cdd6431853a1..88a730e6cfdb 100644 --- a/arch/ia64/sn/kernel/xpc_partition.c +++ b/arch/ia64/sn/kernel/xpc_partition.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. | 6 | * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | 9 | ||
@@ -28,7 +28,7 @@ | |||
28 | #include <asm/sn/sn_sal.h> | 28 | #include <asm/sn/sn_sal.h> |
29 | #include <asm/sn/nodepda.h> | 29 | #include <asm/sn/nodepda.h> |
30 | #include <asm/sn/addrs.h> | 30 | #include <asm/sn/addrs.h> |
31 | #include "xpc.h" | 31 | #include <asm/sn/xpc.h> |
32 | 32 | ||
33 | 33 | ||
34 | /* XPC is exiting flag */ | 34 | /* XPC is exiting flag */ |
@@ -771,7 +771,8 @@ xpc_identify_act_IRQ_req(int nasid) | |||
771 | } | 771 | } |
772 | } | 772 | } |
773 | 773 | ||
774 | if (!xpc_partition_disengaged(part)) { | 774 | if (part->disengage_request_timeout > 0 && |
775 | !xpc_partition_disengaged(part)) { | ||
775 | /* still waiting on other side to disengage from us */ | 776 | /* still waiting on other side to disengage from us */ |
776 | return; | 777 | return; |
777 | } | 778 | } |
@@ -873,6 +874,9 @@ xpc_partition_disengaged(struct xpc_partition *part) | |||
873 | * request in a timely fashion, so assume it's dead. | 874 | * request in a timely fashion, so assume it's dead. |
874 | */ | 875 | */ |
875 | 876 | ||
877 | dev_info(xpc_part, "disengage from remote partition %d " | ||
878 | "timed out\n", partid); | ||
879 | xpc_disengage_request_timedout = 1; | ||
876 | xpc_clear_partition_engaged(1UL << partid); | 880 | xpc_clear_partition_engaged(1UL << partid); |
877 | disengaged = 1; | 881 | disengaged = 1; |
878 | } | 882 | } |
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index 34093476e965..e68332d93171 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c | |||
@@ -218,7 +218,9 @@ void sn_dma_flush(uint64_t addr) | |||
218 | uint64_t flags; | 218 | uint64_t flags; |
219 | uint64_t itte; | 219 | uint64_t itte; |
220 | struct hubdev_info *hubinfo; | 220 | struct hubdev_info *hubinfo; |
221 | volatile struct sn_flush_device_list *p; | 221 | volatile struct sn_flush_device_kernel *p; |
222 | volatile struct sn_flush_device_common *common; | ||
223 | |||
222 | struct sn_flush_nasid_entry *flush_nasid_list; | 224 | struct sn_flush_nasid_entry *flush_nasid_list; |
223 | 225 | ||
224 | if (!sn_ioif_inited) | 226 | if (!sn_ioif_inited) |
@@ -268,17 +270,17 @@ void sn_dma_flush(uint64_t addr) | |||
268 | p = &flush_nasid_list->widget_p[wid_num][0]; | 270 | p = &flush_nasid_list->widget_p[wid_num][0]; |
269 | 271 | ||
270 | /* find a matching BAR */ | 272 | /* find a matching BAR */ |
271 | for (i = 0; i < DEV_PER_WIDGET; i++) { | 273 | for (i = 0; i < DEV_PER_WIDGET; i++,p++) { |
274 | common = p->common; | ||
272 | for (j = 0; j < PCI_ROM_RESOURCE; j++) { | 275 | for (j = 0; j < PCI_ROM_RESOURCE; j++) { |
273 | if (p->sfdl_bar_list[j].start == 0) | 276 | if (common->sfdl_bar_list[j].start == 0) |
274 | break; | 277 | break; |
275 | if (addr >= p->sfdl_bar_list[j].start | 278 | if (addr >= common->sfdl_bar_list[j].start |
276 | && addr <= p->sfdl_bar_list[j].end) | 279 | && addr <= common->sfdl_bar_list[j].end) |
277 | break; | 280 | break; |
278 | } | 281 | } |
279 | if (j < PCI_ROM_RESOURCE && p->sfdl_bar_list[j].start != 0) | 282 | if (j < PCI_ROM_RESOURCE && common->sfdl_bar_list[j].start != 0) |
280 | break; | 283 | break; |
281 | p++; | ||
282 | } | 284 | } |
283 | 285 | ||
284 | /* if no matching BAR, return without doing anything. */ | 286 | /* if no matching BAR, return without doing anything. */ |
@@ -304,24 +306,24 @@ void sn_dma_flush(uint64_t addr) | |||
304 | if ((1 << XWIDGET_PART_REV_NUM_REV(revnum)) & PV907516) { | 306 | if ((1 << XWIDGET_PART_REV_NUM_REV(revnum)) & PV907516) { |
305 | return; | 307 | return; |
306 | } else { | 308 | } else { |
307 | pcireg_wrb_flush_get(p->sfdl_pcibus_info, | 309 | pcireg_wrb_flush_get(common->sfdl_pcibus_info, |
308 | (p->sfdl_slot - 1)); | 310 | (common->sfdl_slot - 1)); |
309 | } | 311 | } |
310 | } else { | 312 | } else { |
311 | spin_lock_irqsave(&((struct sn_flush_device_list *)p)-> | 313 | spin_lock_irqsave((spinlock_t *)&p->sfdl_flush_lock, |
312 | sfdl_flush_lock, flags); | 314 | flags); |
313 | 315 | *common->sfdl_flush_addr = 0; | |
314 | *p->sfdl_flush_addr = 0; | ||
315 | 316 | ||
316 | /* force an interrupt. */ | 317 | /* force an interrupt. */ |
317 | *(volatile uint32_t *)(p->sfdl_force_int_addr) = 1; | 318 | *(volatile uint32_t *)(common->sfdl_force_int_addr) = 1; |
318 | 319 | ||
319 | /* wait for the interrupt to come back. */ | 320 | /* wait for the interrupt to come back. */ |
320 | while (*(p->sfdl_flush_addr) != 0x10f) | 321 | while (*(common->sfdl_flush_addr) != 0x10f) |
321 | cpu_relax(); | 322 | cpu_relax(); |
322 | 323 | ||
323 | /* okay, everything is synched up. */ | 324 | /* okay, everything is synched up. */ |
324 | spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock, flags); | 325 | spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock, |
326 | flags); | ||
325 | } | 327 | } |
326 | return; | 328 | return; |
327 | } | 329 | } |
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index 1f500c81002c..e328e948175d 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c | |||
@@ -92,7 +92,8 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont | |||
92 | cnodeid_t near_cnode; | 92 | cnodeid_t near_cnode; |
93 | struct hubdev_info *hubdev_info; | 93 | struct hubdev_info *hubdev_info; |
94 | struct pcibus_info *soft; | 94 | struct pcibus_info *soft; |
95 | struct sn_flush_device_list *sn_flush_device_list; | 95 | struct sn_flush_device_kernel *sn_flush_device_kernel; |
96 | struct sn_flush_device_common *common; | ||
96 | 97 | ||
97 | if (! IS_PCI_BRIDGE_ASIC(prom_bussoft->bs_asic_type)) { | 98 | if (! IS_PCI_BRIDGE_ASIC(prom_bussoft->bs_asic_type)) { |
98 | return NULL; | 99 | return NULL; |
@@ -137,20 +138,19 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont | |||
137 | hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); | 138 | hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); |
138 | 139 | ||
139 | if (hubdev_info->hdi_flush_nasid_list.widget_p) { | 140 | if (hubdev_info->hdi_flush_nasid_list.widget_p) { |
140 | sn_flush_device_list = hubdev_info->hdi_flush_nasid_list. | 141 | sn_flush_device_kernel = hubdev_info->hdi_flush_nasid_list. |
141 | widget_p[(int)soft->pbi_buscommon.bs_xid]; | 142 | widget_p[(int)soft->pbi_buscommon.bs_xid]; |
142 | if (sn_flush_device_list) { | 143 | if (sn_flush_device_kernel) { |
143 | for (j = 0; j < DEV_PER_WIDGET; | 144 | for (j = 0; j < DEV_PER_WIDGET; |
144 | j++, sn_flush_device_list++) { | 145 | j++, sn_flush_device_kernel++) { |
145 | if (sn_flush_device_list->sfdl_slot == -1) | 146 | common = sn_flush_device_kernel->common; |
147 | if (common->sfdl_slot == -1) | ||
146 | continue; | 148 | continue; |
147 | if ((sn_flush_device_list-> | 149 | if ((common->sfdl_persistent_segment == |
148 | sfdl_persistent_segment == | ||
149 | soft->pbi_buscommon.bs_persist_segment) && | 150 | soft->pbi_buscommon.bs_persist_segment) && |
150 | (sn_flush_device_list-> | 151 | (common->sfdl_persistent_busnum == |
151 | sfdl_persistent_busnum == | ||
152 | soft->pbi_buscommon.bs_persist_busnum)) | 152 | soft->pbi_buscommon.bs_persist_busnum)) |
153 | sn_flush_device_list->sfdl_pcibus_info = | 153 | common->sfdl_pcibus_info = |
154 | soft; | 154 | soft; |
155 | } | 155 | } |
156 | } | 156 | } |
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index d3654a264ef7..44dd82b791d1 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile | |||
@@ -139,17 +139,14 @@ drivers-$(CONFIG_CPM2) += arch/ppc/8260_io/ | |||
139 | 139 | ||
140 | drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ | 140 | drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ |
141 | 141 | ||
142 | defaultimage-$(CONFIG_PPC32) := zImage | 142 | # Default to zImage, override when needed |
143 | defaultimage-y := zImage | ||
143 | defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux | 144 | defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux |
144 | defaultimage-$(CONFIG_PPC_PSERIES) := zImage | ||
145 | KBUILD_IMAGE := $(defaultimage-y) | 145 | KBUILD_IMAGE := $(defaultimage-y) |
146 | all: $(KBUILD_IMAGE) | 146 | all: $(KBUILD_IMAGE) |
147 | 147 | ||
148 | CPPFLAGS_vmlinux.lds := -Upowerpc | 148 | CPPFLAGS_vmlinux.lds := -Upowerpc |
149 | 149 | ||
150 | # All the instructions talk about "make bzImage". | ||
151 | bzImage: zImage | ||
152 | |||
153 | BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage | 150 | BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage |
154 | 151 | ||
155 | .PHONY: $(BOOT_TARGETS) | 152 | .PHONY: $(BOOT_TARGETS) |
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index b53d677f6742..788dec4c7ef3 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
@@ -25,8 +25,8 @@ HOSTCC := gcc | |||
25 | BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \ | 25 | BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \ |
26 | $(shell $(CROSS32CC) -print-file-name=include) -fPIC | 26 | $(shell $(CROSS32CC) -print-file-name=include) -fPIC |
27 | BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc | 27 | BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc |
28 | BOOTLFLAGS := -T $(srctree)/$(src)/zImage.lds | ||
29 | OBJCOPYFLAGS := contents,alloc,load,readonly,data | 28 | OBJCOPYFLAGS := contents,alloc,load,readonly,data |
29 | OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000 | ||
30 | 30 | ||
31 | zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c | 31 | zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c |
32 | zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h | 32 | zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h |
@@ -35,7 +35,7 @@ zliblinuxheader := zlib.h zconf.h zutil.h | |||
35 | $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) | 35 | $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) |
36 | #$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h) | 36 | #$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h) |
37 | 37 | ||
38 | src-boot := string.S prom.c main.c div64.S crt0.S | 38 | src-boot := crt0.S string.S prom.c stdio.c main.c div64.S |
39 | src-boot += $(zlib) | 39 | src-boot += $(zlib) |
40 | src-boot := $(addprefix $(obj)/, $(src-boot)) | 40 | src-boot := $(addprefix $(obj)/, $(src-boot)) |
41 | obj-boot := $(addsuffix .o, $(basename $(src-boot))) | 41 | obj-boot := $(addsuffix .o, $(basename $(src-boot))) |
@@ -70,7 +70,7 @@ quiet_cmd_bootas = BOOTAS $@ | |||
70 | cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< | 70 | cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< |
71 | 71 | ||
72 | quiet_cmd_bootld = BOOTLD $@ | 72 | quiet_cmd_bootld = BOOTLD $@ |
73 | cmd_bootld = $(CROSS32LD) $(BOOTLFLAGS) -o $@ $(2) | 73 | cmd_bootld = $(CROSS32LD) -T $(srctree)/$(src)/$(3) -o $@ $(2) |
74 | 74 | ||
75 | $(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c | 75 | $(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c |
76 | $(call if_changed_dep,bootcc) | 76 | $(call if_changed_dep,bootcc) |
@@ -87,12 +87,14 @@ obj-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.o, $(section))) | |||
87 | src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section))) | 87 | src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section))) |
88 | gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section))) | 88 | gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section))) |
89 | 89 | ||
90 | hostprogs-y := addnote addRamDisk | 90 | hostprogs-y := addnote addRamDisk hack-coff |
91 | targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \ | 91 | |
92 | $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ | 92 | targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \ |
93 | $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ | 93 | zImage.coff zImage.initrd.coff \ |
94 | $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ | 94 | $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ |
95 | vmlinux.initrd | 95 | $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ |
96 | $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ | ||
97 | vmlinux.initrd | ||
96 | extra-y := initrd.o | 98 | extra-y := initrd.o |
97 | 99 | ||
98 | quiet_cmd_ramdisk = RAMDISK $@ | 100 | quiet_cmd_ramdisk = RAMDISK $@ |
@@ -114,6 +116,10 @@ quiet_cmd_addsection = ADDSEC $@ | |||
114 | quiet_cmd_addnote = ADDNOTE $@ | 116 | quiet_cmd_addnote = ADDNOTE $@ |
115 | cmd_addnote = $(obj)/addnote $@ | 117 | cmd_addnote = $(obj)/addnote $@ |
116 | 118 | ||
119 | quiet_cmd_gencoff = COFF $@ | ||
120 | cmd_gencoff = $(OBJCOPY) $(OBJCOPY_COFF_ARGS) $@ && \ | ||
121 | $(obj)/hack-coff $@ | ||
122 | |||
117 | $(call gz-sec, $(required)): $(obj)/kernel-%.gz: % | 123 | $(call gz-sec, $(required)): $(obj)/kernel-%.gz: % |
118 | $(call if_changed,gzip) | 124 | $(call if_changed,gzip) |
119 | 125 | ||
@@ -127,22 +133,35 @@ $(call obj-sec, $(required) $(initrd)): $(obj)/kernel-%.o: $(obj)/kernel-%.c | |||
127 | $(call if_changed_dep,bootcc) | 133 | $(call if_changed_dep,bootcc) |
128 | $(call cmd,addsection) | 134 | $(call cmd,addsection) |
129 | 135 | ||
130 | $(obj)/zImage.vmode: obj-boot += $(call obj-sec, $(required)) | 136 | $(obj)/zImage.vmode $(obj)/zImage.coff: obj-boot += $(call obj-sec, $(required)) |
131 | $(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.lds | 137 | $(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.lds |
132 | $(call cmd,bootld,$(obj-boot)) | 138 | $(call cmd,bootld,$(obj-boot),zImage.lds) |
133 | 139 | ||
134 | $(obj)/zImage.initrd.vmode: obj-boot += $(call obj-sec, $(required) $(initrd)) | 140 | $(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff: obj-boot += $(call obj-sec, $(required) $(initrd)) |
135 | $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds | 141 | $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds |
136 | $(call cmd,bootld,$(obj-boot)) | 142 | $(call cmd,bootld,$(obj-boot),zImage.lds) |
143 | |||
144 | # For 32-bit powermacs, build the COFF images as well as the ELF images. | ||
145 | coffimage-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.coff | ||
146 | coffrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.initrd.coff | ||
137 | 147 | ||
138 | $(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote | 148 | $(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote $(coffimage-y-y) |
139 | @cp -f $< $@ | 149 | @cp -f $< $@ |
140 | $(call if_changed,addnote) | 150 | $(call if_changed,addnote) |
141 | 151 | ||
142 | $(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote | 152 | $(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote $(coffrdimg-y-y) |
143 | @cp -f $< $@ | 153 | @cp -f $< $@ |
144 | $(call if_changed,addnote) | 154 | $(call if_changed,addnote) |
145 | 155 | ||
156 | $(obj)/zImage.coff: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff | ||
157 | $(call cmd,bootld,$(obj-boot),zImage.coff.lds) | ||
158 | $(call cmd,gencoff) | ||
159 | |||
160 | $(obj)/zImage.initrd.coff: $(call obj-sec, $(required) $(initrd)) $(obj-boot) \ | ||
161 | $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff | ||
162 | $(call cmd,bootld,$(obj-boot),zImage.coff.lds) | ||
163 | $(call cmd,gencoff) | ||
164 | |||
146 | #----------------------------------------------------------- | 165 | #----------------------------------------------------------- |
147 | # build u-boot images | 166 | # build u-boot images |
148 | #----------------------------------------------------------- | 167 | #----------------------------------------------------------- |
diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S index d2f2ace56cd3..e0192c26037b 100644 --- a/arch/powerpc/boot/crt0.S +++ b/arch/powerpc/boot/crt0.S | |||
@@ -12,17 +12,23 @@ | |||
12 | #include "ppc_asm.h" | 12 | #include "ppc_asm.h" |
13 | 13 | ||
14 | .text | 14 | .text |
15 | /* a procedure descriptor used when booting this as a COFF file */ | ||
16 | _zimage_start_opd: | ||
17 | .long _zimage_start, 0, 0, 0 | ||
18 | |||
15 | .globl _zimage_start | 19 | .globl _zimage_start |
16 | _zimage_start: | 20 | _zimage_start: |
21 | /* Work out the offset between the address we were linked at | ||
22 | and the address where we're running. */ | ||
17 | bl 1f | 23 | bl 1f |
18 | 24 | 1: mflr r0 | |
19 | 1: | ||
20 | mflr r0 | ||
21 | lis r9,1b@ha | 25 | lis r9,1b@ha |
22 | addi r9,r9,1b@l | 26 | addi r9,r9,1b@l |
23 | subf. r0,r9,r0 | 27 | subf. r0,r9,r0 |
24 | beq 3f | 28 | beq 3f /* if running at same address as linked */ |
25 | 29 | ||
30 | /* The .got2 section contains a list of addresses, so add | ||
31 | the address offset onto each entry. */ | ||
26 | lis r9,__got2_start@ha | 32 | lis r9,__got2_start@ha |
27 | addi r9,r9,__got2_start@l | 33 | addi r9,r9,__got2_start@l |
28 | lis r8,__got2_end@ha | 34 | lis r8,__got2_end@ha |
@@ -32,15 +38,14 @@ _zimage_start: | |||
32 | srwi. r8,r8,2 | 38 | srwi. r8,r8,2 |
33 | mtctr r8 | 39 | mtctr r8 |
34 | add r9,r0,r9 | 40 | add r9,r0,r9 |
35 | 2: | 41 | 2: lwz r8,0(r9) |
36 | lwz r8,0(r9) | ||
37 | add r8,r8,r0 | 42 | add r8,r8,r0 |
38 | stw r8,0(r9) | 43 | stw r8,0(r9) |
39 | addi r9,r9,4 | 44 | addi r9,r9,4 |
40 | bdnz 2b | 45 | bdnz 2b |
41 | 46 | ||
42 | 3: | 47 | /* Do a cache flush for our text, in case OF didn't */ |
43 | lis r9,_start@h | 48 | 3: lis r9,_start@h |
44 | add r9,r0,r9 | 49 | add r9,r0,r9 |
45 | lis r8,_etext@ha | 50 | lis r8,_etext@ha |
46 | addi r8,r8,_etext@l | 51 | addi r8,r8,_etext@l |
diff --git a/arch/powerpc/boot/hack-coff.c b/arch/powerpc/boot/hack-coff.c new file mode 100644 index 000000000000..5e5a6573a1ef --- /dev/null +++ b/arch/powerpc/boot/hack-coff.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * hack-coff.c - hack the header of an xcoff file to fill in | ||
3 | * a few fields needed by the Open Firmware xcoff loader on | ||
4 | * Power Macs but not initialized by objcopy. | ||
5 | * | ||
6 | * Copyright (C) Paul Mackerras 1997. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | */ | ||
13 | #include <stdio.h> | ||
14 | #include <stdlib.h> | ||
15 | #include <unistd.h> | ||
16 | #include <fcntl.h> | ||
17 | #include <string.h> | ||
18 | #include "rs6000.h" | ||
19 | |||
20 | #define AOUT_MAGIC 0x010b | ||
21 | |||
22 | #define get_16be(x) ((((unsigned char *)(x))[0] << 8) \ | ||
23 | + ((unsigned char *)(x))[1]) | ||
24 | #define put_16be(x, v) (((unsigned char *)(x))[0] = (v) >> 8, \ | ||
25 | ((unsigned char *)(x))[1] = (v) & 0xff) | ||
26 | #define get_32be(x) ((((unsigned char *)(x))[0] << 24) \ | ||
27 | + (((unsigned char *)(x))[1] << 16) \ | ||
28 | + (((unsigned char *)(x))[2] << 8) \ | ||
29 | + ((unsigned char *)(x))[3]) | ||
30 | |||
31 | int | ||
32 | main(int ac, char **av) | ||
33 | { | ||
34 | int fd; | ||
35 | int i, nsect; | ||
36 | int aoutsz; | ||
37 | struct external_filehdr fhdr; | ||
38 | AOUTHDR aout; | ||
39 | struct external_scnhdr shdr; | ||
40 | |||
41 | if (ac != 2) { | ||
42 | fprintf(stderr, "Usage: hack-coff coff-file\n"); | ||
43 | exit(1); | ||
44 | } | ||
45 | if ((fd = open(av[1], 2)) == -1) { | ||
46 | perror(av[2]); | ||
47 | exit(1); | ||
48 | } | ||
49 | if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr)) | ||
50 | goto readerr; | ||
51 | i = get_16be(fhdr.f_magic); | ||
52 | if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) { | ||
53 | fprintf(stderr, "%s: not an xcoff file\n", av[1]); | ||
54 | exit(1); | ||
55 | } | ||
56 | aoutsz = get_16be(fhdr.f_opthdr); | ||
57 | if (read(fd, &aout, aoutsz) != aoutsz) | ||
58 | goto readerr; | ||
59 | nsect = get_16be(fhdr.f_nscns); | ||
60 | for (i = 0; i < nsect; ++i) { | ||
61 | if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) | ||
62 | goto readerr; | ||
63 | if (strcmp(shdr.s_name, ".text") == 0) { | ||
64 | put_16be(aout.o_snentry, i+1); | ||
65 | put_16be(aout.o_sntext, i+1); | ||
66 | } else if (strcmp(shdr.s_name, ".data") == 0) { | ||
67 | put_16be(aout.o_sndata, i+1); | ||
68 | } else if (strcmp(shdr.s_name, ".bss") == 0) { | ||
69 | put_16be(aout.o_snbss, i+1); | ||
70 | } | ||
71 | } | ||
72 | put_16be(aout.magic, AOUT_MAGIC); | ||
73 | if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1 | ||
74 | || write(fd, &aout, aoutsz) != aoutsz) { | ||
75 | fprintf(stderr, "%s: write error\n", av[1]); | ||
76 | exit(1); | ||
77 | } | ||
78 | close(fd); | ||
79 | exit(0); | ||
80 | |||
81 | readerr: | ||
82 | fprintf(stderr, "%s: read error or file too short\n", av[1]); | ||
83 | exit(1); | ||
84 | } | ||
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index 64ec93116fa6..55ec59867250 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c | |||
@@ -21,8 +21,8 @@ extern void flush_cache(void *, unsigned long); | |||
21 | 21 | ||
22 | 22 | ||
23 | /* Value picked to match that used by yaboot */ | 23 | /* Value picked to match that used by yaboot */ |
24 | #define PROG_START 0x01400000 | 24 | #define PROG_START 0x01400000 /* only used on 64-bit systems */ |
25 | #define RAM_END (512<<20) // Fixme: use OF */ | 25 | #define RAM_END (512<<20) /* Fixme: use OF */ |
26 | #define ONE_MB 0x100000 | 26 | #define ONE_MB 0x100000 |
27 | 27 | ||
28 | extern char _start[]; | 28 | extern char _start[]; |
@@ -160,6 +160,17 @@ static int is_elf64(void *hdr) | |||
160 | elfoffset = (unsigned long)elf64ph->p_offset; | 160 | elfoffset = (unsigned long)elf64ph->p_offset; |
161 | vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset; | 161 | vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset; |
162 | vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset; | 162 | vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset; |
163 | |||
164 | #if defined(PROG_START) | ||
165 | /* | ||
166 | * Maintain a "magic" minimum address. This keeps some older | ||
167 | * firmware platforms running. | ||
168 | */ | ||
169 | |||
170 | if (claim_base < PROG_START) | ||
171 | claim_base = PROG_START; | ||
172 | #endif | ||
173 | |||
163 | return 1; | 174 | return 1; |
164 | } | 175 | } |
165 | 176 | ||
@@ -206,12 +217,18 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) | |||
206 | exit(); | 217 | exit(); |
207 | if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4) | 218 | if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4) |
208 | exit(); | 219 | exit(); |
209 | stderr = stdout; | ||
210 | if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4) | ||
211 | exit(); | ||
212 | 220 | ||
213 | printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp); | 221 | printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp); |
214 | 222 | ||
223 | /* | ||
224 | * The first available claim_base must be above the end of the | ||
225 | * the loaded kernel wrapper file (_start to _end includes the | ||
226 | * initrd image if it is present) and rounded up to a nice | ||
227 | * 1 MB boundary for good measure. | ||
228 | */ | ||
229 | |||
230 | claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB); | ||
231 | |||
215 | vmlinuz.addr = (unsigned long)_vmlinux_start; | 232 | vmlinuz.addr = (unsigned long)_vmlinux_start; |
216 | vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); | 233 | vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); |
217 | 234 | ||
@@ -228,25 +245,6 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) | |||
228 | exit(); | 245 | exit(); |
229 | } | 246 | } |
230 | 247 | ||
231 | /* | ||
232 | * The first available claim_base must be above the end of the | ||
233 | * the loaded kernel wrapper file (_start to _end includes the | ||
234 | * initrd image if it is present) and rounded up to a nice | ||
235 | * 1 MB boundary for good measure. | ||
236 | */ | ||
237 | |||
238 | claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB); | ||
239 | |||
240 | #if defined(PROG_START) | ||
241 | /* | ||
242 | * Maintain a "magic" minimum address. This keeps some older | ||
243 | * firmware platforms running. | ||
244 | */ | ||
245 | |||
246 | if (claim_base < PROG_START) | ||
247 | claim_base = PROG_START; | ||
248 | #endif | ||
249 | |||
250 | /* We need to claim the memsize plus the file offset since gzip | 248 | /* We need to claim the memsize plus the file offset since gzip |
251 | * will expand the header (file offset), then the kernel, then | 249 | * will expand the header (file offset), then the kernel, then |
252 | * possible rubbish we don't care about. But the kernel bss must | 250 | * possible rubbish we don't care about. But the kernel bss must |
diff --git a/arch/powerpc/boot/prom.c b/arch/powerpc/boot/prom.c index 4bea2f4dcb06..fa0057736f6b 100644 --- a/arch/powerpc/boot/prom.c +++ b/arch/powerpc/boot/prom.c | |||
@@ -13,487 +13,153 @@ | |||
13 | #include "prom.h" | 13 | #include "prom.h" |
14 | 14 | ||
15 | int (*prom)(void *); | 15 | int (*prom)(void *); |
16 | phandle chosen_handle; | ||
17 | ihandle stdout; | ||
16 | 18 | ||
17 | void *chosen_handle; | 19 | int call_prom(const char *service, int nargs, int nret, ...) |
18 | |||
19 | void *stdin; | ||
20 | void *stdout; | ||
21 | void *stderr; | ||
22 | |||
23 | |||
24 | int | ||
25 | write(void *handle, void *ptr, int nb) | ||
26 | { | ||
27 | struct prom_args { | ||
28 | char *service; | ||
29 | int nargs; | ||
30 | int nret; | ||
31 | void *ihandle; | ||
32 | void *addr; | ||
33 | int len; | ||
34 | int actual; | ||
35 | } args; | ||
36 | |||
37 | args.service = "write"; | ||
38 | args.nargs = 3; | ||
39 | args.nret = 1; | ||
40 | args.ihandle = handle; | ||
41 | args.addr = ptr; | ||
42 | args.len = nb; | ||
43 | args.actual = -1; | ||
44 | (*prom)(&args); | ||
45 | return args.actual; | ||
46 | } | ||
47 | |||
48 | int | ||
49 | read(void *handle, void *ptr, int nb) | ||
50 | { | 20 | { |
21 | int i; | ||
51 | struct prom_args { | 22 | struct prom_args { |
52 | char *service; | 23 | const char *service; |
53 | int nargs; | 24 | int nargs; |
54 | int nret; | 25 | int nret; |
55 | void *ihandle; | 26 | unsigned int args[12]; |
56 | void *addr; | ||
57 | int len; | ||
58 | int actual; | ||
59 | } args; | ||
60 | |||
61 | args.service = "read"; | ||
62 | args.nargs = 3; | ||
63 | args.nret = 1; | ||
64 | args.ihandle = handle; | ||
65 | args.addr = ptr; | ||
66 | args.len = nb; | ||
67 | args.actual = -1; | ||
68 | (*prom)(&args); | ||
69 | return args.actual; | ||
70 | } | ||
71 | |||
72 | void | ||
73 | exit() | ||
74 | { | ||
75 | struct prom_args { | ||
76 | char *service; | ||
77 | } args; | ||
78 | |||
79 | for (;;) { | ||
80 | args.service = "exit"; | ||
81 | (*prom)(&args); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | void | ||
86 | pause(void) | ||
87 | { | ||
88 | struct prom_args { | ||
89 | char *service; | ||
90 | } args; | 27 | } args; |
28 | va_list list; | ||
91 | 29 | ||
92 | args.service = "enter"; | 30 | args.service = service; |
93 | (*prom)(&args); | 31 | args.nargs = nargs; |
94 | } | 32 | args.nret = nret; |
95 | 33 | ||
96 | void * | 34 | va_start(list, nret); |
97 | finddevice(const char *name) | 35 | for (i = 0; i < nargs; i++) |
98 | { | 36 | args.args[i] = va_arg(list, unsigned int); |
99 | struct prom_args { | 37 | va_end(list); |
100 | char *service; | ||
101 | int nargs; | ||
102 | int nret; | ||
103 | const char *devspec; | ||
104 | void *phandle; | ||
105 | } args; | ||
106 | 38 | ||
107 | args.service = "finddevice"; | 39 | for (i = 0; i < nret; i++) |
108 | args.nargs = 1; | 40 | args.args[nargs+i] = 0; |
109 | args.nret = 1; | ||
110 | args.devspec = name; | ||
111 | args.phandle = (void *) -1; | ||
112 | (*prom)(&args); | ||
113 | return args.phandle; | ||
114 | } | ||
115 | 41 | ||
116 | void * | 42 | if (prom(&args) < 0) |
117 | claim(unsigned long virt, unsigned long size, unsigned long align) | 43 | return -1; |
118 | { | ||
119 | struct prom_args { | ||
120 | char *service; | ||
121 | int nargs; | ||
122 | int nret; | ||
123 | unsigned int virt; | ||
124 | unsigned int size; | ||
125 | unsigned int align; | ||
126 | void *ret; | ||
127 | } args; | ||
128 | 44 | ||
129 | args.service = "claim"; | 45 | return (nret > 0)? args.args[nargs]: 0; |
130 | args.nargs = 3; | ||
131 | args.nret = 1; | ||
132 | args.virt = virt; | ||
133 | args.size = size; | ||
134 | args.align = align; | ||
135 | (*prom)(&args); | ||
136 | return args.ret; | ||
137 | } | 46 | } |
138 | 47 | ||
139 | int | 48 | int call_prom_ret(const char *service, int nargs, int nret, |
140 | getprop(void *phandle, const char *name, void *buf, int buflen) | 49 | unsigned int *rets, ...) |
141 | { | 50 | { |
51 | int i; | ||
142 | struct prom_args { | 52 | struct prom_args { |
143 | char *service; | 53 | const char *service; |
144 | int nargs; | 54 | int nargs; |
145 | int nret; | 55 | int nret; |
146 | void *phandle; | 56 | unsigned int args[12]; |
147 | const char *name; | ||
148 | void *buf; | ||
149 | int buflen; | ||
150 | int size; | ||
151 | } args; | 57 | } args; |
58 | va_list list; | ||
152 | 59 | ||
153 | args.service = "getprop"; | 60 | args.service = service; |
154 | args.nargs = 4; | 61 | args.nargs = nargs; |
155 | args.nret = 1; | 62 | args.nret = nret; |
156 | args.phandle = phandle; | ||
157 | args.name = name; | ||
158 | args.buf = buf; | ||
159 | args.buflen = buflen; | ||
160 | args.size = -1; | ||
161 | (*prom)(&args); | ||
162 | return args.size; | ||
163 | } | ||
164 | 63 | ||
165 | int | 64 | va_start(list, rets); |
166 | putc(int c, void *f) | 65 | for (i = 0; i < nargs; i++) |
167 | { | 66 | args.args[i] = va_arg(list, unsigned int); |
168 | char ch = c; | 67 | va_end(list); |
169 | 68 | ||
170 | if (c == '\n') | 69 | for (i = 0; i < nret; i++) |
171 | putc('\r', f); | 70 | args.args[nargs+i] = 0; |
172 | return write(f, &ch, 1) == 1? c: -1; | ||
173 | } | ||
174 | 71 | ||
175 | int | 72 | if (prom(&args) < 0) |
176 | putchar(int c) | 73 | return -1; |
177 | { | ||
178 | return putc(c, stdout); | ||
179 | } | ||
180 | 74 | ||
181 | int | 75 | if (rets != (void *) 0) |
182 | fputs(char *str, void *f) | 76 | for (i = 1; i < nret; ++i) |
183 | { | 77 | rets[i-1] = args.args[nargs+i]; |
184 | int n = strlen(str); | ||
185 | 78 | ||
186 | return write(f, str, n) == n? 0: -1; | 79 | return (nret > 0)? args.args[nargs]: 0; |
187 | } | 80 | } |
188 | 81 | ||
189 | size_t strnlen(const char * s, size_t count) | 82 | int write(void *handle, void *ptr, int nb) |
190 | { | 83 | { |
191 | const char *sc; | 84 | return call_prom("write", 3, 1, handle, ptr, nb); |
192 | |||
193 | for (sc = s; count-- && *sc != '\0'; ++sc) | ||
194 | /* nothing */; | ||
195 | return sc - s; | ||
196 | } | 85 | } |
197 | 86 | ||
198 | extern unsigned int __div64_32(unsigned long long *dividend, | 87 | /* |
199 | unsigned int divisor); | 88 | * Older OF's require that when claiming a specific range of addresses, |
200 | 89 | * we claim the physical space in the /memory node and the virtual | |
201 | /* The unnecessary pointer compare is there | 90 | * space in the chosen mmu node, and then do a map operation to |
202 | * to check for type safety (n must be 64bit) | 91 | * map virtual to physical. |
203 | */ | 92 | */ |
204 | # define do_div(n,base) ({ \ | 93 | static int need_map = -1; |
205 | unsigned int __base = (base); \ | 94 | static ihandle chosen_mmu; |
206 | unsigned int __rem; \ | 95 | static phandle memory; |
207 | (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \ | ||
208 | if (((n) >> 32) == 0) { \ | ||
209 | __rem = (unsigned int)(n) % __base; \ | ||
210 | (n) = (unsigned int)(n) / __base; \ | ||
211 | } else \ | ||
212 | __rem = __div64_32(&(n), __base); \ | ||
213 | __rem; \ | ||
214 | }) | ||
215 | 96 | ||
216 | static int skip_atoi(const char **s) | 97 | /* returns true if s2 is a prefix of s1 */ |
98 | static int string_match(const char *s1, const char *s2) | ||
217 | { | 99 | { |
218 | int i, c; | 100 | for (; *s2; ++s2) |
219 | 101 | if (*s1++ != *s2) | |
220 | for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s) | 102 | return 0; |
221 | i = i*10 + c - '0'; | 103 | return 1; |
222 | return i; | ||
223 | } | 104 | } |
224 | 105 | ||
225 | #define ZEROPAD 1 /* pad with zero */ | 106 | static int check_of_version(void) |
226 | #define SIGN 2 /* unsigned/signed long */ | ||
227 | #define PLUS 4 /* show plus */ | ||
228 | #define SPACE 8 /* space if plus */ | ||
229 | #define LEFT 16 /* left justified */ | ||
230 | #define SPECIAL 32 /* 0x */ | ||
231 | #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ | ||
232 | |||
233 | static char * number(char * str, unsigned long long num, int base, int size, int precision, int type) | ||
234 | { | 107 | { |
235 | char c,sign,tmp[66]; | 108 | phandle oprom, chosen; |
236 | const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; | 109 | char version[64]; |
237 | int i; | ||
238 | 110 | ||
239 | if (type & LARGE) | 111 | oprom = finddevice("/openprom"); |
240 | digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | 112 | if (oprom == (phandle) -1) |
241 | if (type & LEFT) | ||
242 | type &= ~ZEROPAD; | ||
243 | if (base < 2 || base > 36) | ||
244 | return 0; | 113 | return 0; |
245 | c = (type & ZEROPAD) ? '0' : ' '; | 114 | if (getprop(oprom, "model", version, sizeof(version)) <= 0) |
246 | sign = 0; | 115 | return 0; |
247 | if (type & SIGN) { | 116 | version[sizeof(version)-1] = 0; |
248 | if ((signed long long)num < 0) { | 117 | printf("OF version = '%s'\r\n", version); |
249 | sign = '-'; | 118 | if (!string_match(version, "Open Firmware, 1.") |
250 | num = - (signed long long)num; | 119 | && !string_match(version, "FirmWorks,3.")) |
251 | size--; | 120 | return 0; |
252 | } else if (type & PLUS) { | 121 | chosen = finddevice("/chosen"); |
253 | sign = '+'; | 122 | if (chosen == (phandle) -1) { |
254 | size--; | 123 | chosen = finddevice("/chosen@0"); |
255 | } else if (type & SPACE) { | 124 | if (chosen == (phandle) -1) { |
256 | sign = ' '; | 125 | printf("no chosen\n"); |
257 | size--; | 126 | return 0; |
258 | } | 127 | } |
259 | } | 128 | } |
260 | if (type & SPECIAL) { | 129 | if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { |
261 | if (base == 16) | 130 | printf("no mmu\n"); |
262 | size -= 2; | 131 | return 0; |
263 | else if (base == 8) | ||
264 | size--; | ||
265 | } | ||
266 | i = 0; | ||
267 | if (num == 0) | ||
268 | tmp[i++]='0'; | ||
269 | else while (num != 0) { | ||
270 | tmp[i++] = digits[do_div(num, base)]; | ||
271 | } | 132 | } |
272 | if (i > precision) | 133 | memory = (ihandle) call_prom("open", 1, 1, "/memory"); |
273 | precision = i; | 134 | if (memory == (ihandle) -1) { |
274 | size -= precision; | 135 | memory = (ihandle) call_prom("open", 1, 1, "/memory@0"); |
275 | if (!(type&(ZEROPAD+LEFT))) | 136 | if (memory == (ihandle) -1) { |
276 | while(size-->0) | 137 | printf("no memory node\n"); |
277 | *str++ = ' '; | 138 | return 0; |
278 | if (sign) | ||
279 | *str++ = sign; | ||
280 | if (type & SPECIAL) { | ||
281 | if (base==8) | ||
282 | *str++ = '0'; | ||
283 | else if (base==16) { | ||
284 | *str++ = '0'; | ||
285 | *str++ = digits[33]; | ||
286 | } | 139 | } |
287 | } | 140 | } |
288 | if (!(type & LEFT)) | 141 | printf("old OF detected\r\n"); |
289 | while (size-- > 0) | 142 | return 1; |
290 | *str++ = c; | ||
291 | while (i < precision--) | ||
292 | *str++ = '0'; | ||
293 | while (i-- > 0) | ||
294 | *str++ = tmp[i]; | ||
295 | while (size-- > 0) | ||
296 | *str++ = ' '; | ||
297 | return str; | ||
298 | } | 143 | } |
299 | 144 | ||
300 | int vsprintf(char *buf, const char *fmt, va_list args) | 145 | void *claim(unsigned long virt, unsigned long size, unsigned long align) |
301 | { | 146 | { |
302 | int len; | 147 | int ret; |
303 | unsigned long long num; | 148 | unsigned int result; |
304 | int i, base; | ||
305 | char * str; | ||
306 | const char *s; | ||
307 | |||
308 | int flags; /* flags to number() */ | ||
309 | |||
310 | int field_width; /* width of output field */ | ||
311 | int precision; /* min. # of digits for integers; max | ||
312 | number of chars for from string */ | ||
313 | int qualifier; /* 'h', 'l', or 'L' for integer fields */ | ||
314 | /* 'z' support added 23/7/1999 S.H. */ | ||
315 | /* 'z' changed to 'Z' --davidm 1/25/99 */ | ||
316 | 149 | ||
150 | if (need_map < 0) | ||
151 | need_map = check_of_version(); | ||
152 | if (align || !need_map) | ||
153 | return (void *) call_prom("claim", 3, 1, virt, size, align); | ||
317 | 154 | ||
318 | for (str=buf ; *fmt ; ++fmt) { | 155 | ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory, |
319 | if (*fmt != '%') { | 156 | align, size, virt); |
320 | *str++ = *fmt; | 157 | if (ret != 0 || result == -1) |
321 | continue; | 158 | return (void *) -1; |
322 | } | 159 | ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, |
323 | 160 | align, size, virt); | |
324 | /* process flags */ | 161 | /* 0x12 == coherent + read/write */ |
325 | flags = 0; | 162 | ret = call_prom("call-method", 6, 1, "map", chosen_mmu, |
326 | repeat: | 163 | 0x12, size, virt, virt); |
327 | ++fmt; /* this also skips first '%' */ | 164 | return (void *) virt; |
328 | switch (*fmt) { | ||
329 | case '-': flags |= LEFT; goto repeat; | ||
330 | case '+': flags |= PLUS; goto repeat; | ||
331 | case ' ': flags |= SPACE; goto repeat; | ||
332 | case '#': flags |= SPECIAL; goto repeat; | ||
333 | case '0': flags |= ZEROPAD; goto repeat; | ||
334 | } | ||
335 | |||
336 | /* get field width */ | ||
337 | field_width = -1; | ||
338 | if ('0' <= *fmt && *fmt <= '9') | ||
339 | field_width = skip_atoi(&fmt); | ||
340 | else if (*fmt == '*') { | ||
341 | ++fmt; | ||
342 | /* it's the next argument */ | ||
343 | field_width = va_arg(args, int); | ||
344 | if (field_width < 0) { | ||
345 | field_width = -field_width; | ||
346 | flags |= LEFT; | ||
347 | } | ||
348 | } | ||
349 | |||
350 | /* get the precision */ | ||
351 | precision = -1; | ||
352 | if (*fmt == '.') { | ||
353 | ++fmt; | ||
354 | if ('0' <= *fmt && *fmt <= '9') | ||
355 | precision = skip_atoi(&fmt); | ||
356 | else if (*fmt == '*') { | ||
357 | ++fmt; | ||
358 | /* it's the next argument */ | ||
359 | precision = va_arg(args, int); | ||
360 | } | ||
361 | if (precision < 0) | ||
362 | precision = 0; | ||
363 | } | ||
364 | |||
365 | /* get the conversion qualifier */ | ||
366 | qualifier = -1; | ||
367 | if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { | ||
368 | qualifier = *fmt; | ||
369 | ++fmt; | ||
370 | } | ||
371 | |||
372 | /* default base */ | ||
373 | base = 10; | ||
374 | |||
375 | switch (*fmt) { | ||
376 | case 'c': | ||
377 | if (!(flags & LEFT)) | ||
378 | while (--field_width > 0) | ||
379 | *str++ = ' '; | ||
380 | *str++ = (unsigned char) va_arg(args, int); | ||
381 | while (--field_width > 0) | ||
382 | *str++ = ' '; | ||
383 | continue; | ||
384 | |||
385 | case 's': | ||
386 | s = va_arg(args, char *); | ||
387 | if (!s) | ||
388 | s = "<NULL>"; | ||
389 | |||
390 | len = strnlen(s, precision); | ||
391 | |||
392 | if (!(flags & LEFT)) | ||
393 | while (len < field_width--) | ||
394 | *str++ = ' '; | ||
395 | for (i = 0; i < len; ++i) | ||
396 | *str++ = *s++; | ||
397 | while (len < field_width--) | ||
398 | *str++ = ' '; | ||
399 | continue; | ||
400 | |||
401 | case 'p': | ||
402 | if (field_width == -1) { | ||
403 | field_width = 2*sizeof(void *); | ||
404 | flags |= ZEROPAD; | ||
405 | } | ||
406 | str = number(str, | ||
407 | (unsigned long) va_arg(args, void *), 16, | ||
408 | field_width, precision, flags); | ||
409 | continue; | ||
410 | |||
411 | |||
412 | case 'n': | ||
413 | if (qualifier == 'l') { | ||
414 | long * ip = va_arg(args, long *); | ||
415 | *ip = (str - buf); | ||
416 | } else if (qualifier == 'Z') { | ||
417 | size_t * ip = va_arg(args, size_t *); | ||
418 | *ip = (str - buf); | ||
419 | } else { | ||
420 | int * ip = va_arg(args, int *); | ||
421 | *ip = (str - buf); | ||
422 | } | ||
423 | continue; | ||
424 | |||
425 | case '%': | ||
426 | *str++ = '%'; | ||
427 | continue; | ||
428 | |||
429 | /* integer number formats - set up the flags and "break" */ | ||
430 | case 'o': | ||
431 | base = 8; | ||
432 | break; | ||
433 | |||
434 | case 'X': | ||
435 | flags |= LARGE; | ||
436 | case 'x': | ||
437 | base = 16; | ||
438 | break; | ||
439 | |||
440 | case 'd': | ||
441 | case 'i': | ||
442 | flags |= SIGN; | ||
443 | case 'u': | ||
444 | break; | ||
445 | |||
446 | default: | ||
447 | *str++ = '%'; | ||
448 | if (*fmt) | ||
449 | *str++ = *fmt; | ||
450 | else | ||
451 | --fmt; | ||
452 | continue; | ||
453 | } | ||
454 | if (qualifier == 'l') { | ||
455 | num = va_arg(args, unsigned long); | ||
456 | if (flags & SIGN) | ||
457 | num = (signed long) num; | ||
458 | } else if (qualifier == 'Z') { | ||
459 | num = va_arg(args, size_t); | ||
460 | } else if (qualifier == 'h') { | ||
461 | num = (unsigned short) va_arg(args, int); | ||
462 | if (flags & SIGN) | ||
463 | num = (signed short) num; | ||
464 | } else { | ||
465 | num = va_arg(args, unsigned int); | ||
466 | if (flags & SIGN) | ||
467 | num = (signed int) num; | ||
468 | } | ||
469 | str = number(str, num, base, field_width, precision, flags); | ||
470 | } | ||
471 | *str = '\0'; | ||
472 | return str-buf; | ||
473 | } | ||
474 | |||
475 | int sprintf(char * buf, const char *fmt, ...) | ||
476 | { | ||
477 | va_list args; | ||
478 | int i; | ||
479 | |||
480 | va_start(args, fmt); | ||
481 | i=vsprintf(buf,fmt,args); | ||
482 | va_end(args); | ||
483 | return i; | ||
484 | } | ||
485 | |||
486 | static char sprint_buf[1024]; | ||
487 | |||
488 | int | ||
489 | printf(const char *fmt, ...) | ||
490 | { | ||
491 | va_list args; | ||
492 | int n; | ||
493 | |||
494 | va_start(args, fmt); | ||
495 | n = vsprintf(sprint_buf, fmt, args); | ||
496 | va_end(args); | ||
497 | write(stdout, sprint_buf, n); | ||
498 | return n; | ||
499 | } | 165 | } |
diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h index 96ab5aec740c..3e2ddd4a5a81 100644 --- a/arch/powerpc/boot/prom.h +++ b/arch/powerpc/boot/prom.h | |||
@@ -1,18 +1,34 @@ | |||
1 | #ifndef _PPC_BOOT_PROM_H_ | 1 | #ifndef _PPC_BOOT_PROM_H_ |
2 | #define _PPC_BOOT_PROM_H_ | 2 | #define _PPC_BOOT_PROM_H_ |
3 | 3 | ||
4 | typedef void *phandle; | ||
5 | typedef void *ihandle; | ||
6 | |||
4 | extern int (*prom) (void *); | 7 | extern int (*prom) (void *); |
5 | extern void *chosen_handle; | 8 | extern phandle chosen_handle; |
9 | extern ihandle stdout; | ||
6 | 10 | ||
7 | extern void *stdin; | 11 | int call_prom(const char *service, int nargs, int nret, ...); |
8 | extern void *stdout; | 12 | int call_prom_ret(const char *service, int nargs, int nret, |
9 | extern void *stderr; | 13 | unsigned int *rets, ...); |
10 | 14 | ||
11 | extern int write(void *handle, void *ptr, int nb); | 15 | extern int write(void *handle, void *ptr, int nb); |
12 | extern int read(void *handle, void *ptr, int nb); | 16 | extern void *claim(unsigned long virt, unsigned long size, unsigned long aln); |
13 | extern void exit(void); | 17 | |
14 | extern void pause(void); | 18 | static inline void exit(void) |
15 | extern void *finddevice(const char *); | 19 | { |
16 | extern void *claim(unsigned long virt, unsigned long size, unsigned long align); | 20 | call_prom("exit", 0, 0); |
17 | extern int getprop(void *phandle, const char *name, void *buf, int buflen); | 21 | } |
22 | |||
23 | static inline phandle finddevice(const char *name) | ||
24 | { | ||
25 | return (phandle) call_prom("finddevice", 1, 1, name); | ||
26 | } | ||
27 | |||
28 | static inline int getprop(void *phandle, const char *name, | ||
29 | void *buf, int buflen) | ||
30 | { | ||
31 | return call_prom("getprop", 4, 1, phandle, name, buf, buflen); | ||
32 | } | ||
33 | |||
18 | #endif /* _PPC_BOOT_PROM_H_ */ | 34 | #endif /* _PPC_BOOT_PROM_H_ */ |
diff --git a/arch/powerpc/boot/rs6000.h b/arch/powerpc/boot/rs6000.h new file mode 100644 index 000000000000..433f45084e41 --- /dev/null +++ b/arch/powerpc/boot/rs6000.h | |||
@@ -0,0 +1,243 @@ | |||
1 | /* IBM RS/6000 "XCOFF" file definitions for BFD. | ||
2 | Copyright (C) 1990, 1991 Free Software Foundation, Inc. | ||
3 | FIXME: Can someone provide a transliteration of this name into ASCII? | ||
4 | Using the following chars caused a compiler warning on HIUX (so I replaced | ||
5 | them with octal escapes), and isn't useful without an understanding of what | ||
6 | character set it is. | ||
7 | Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM | ||
8 | and John Gilmore of Cygnus Support. */ | ||
9 | |||
10 | /********************** FILE HEADER **********************/ | ||
11 | |||
12 | struct external_filehdr { | ||
13 | char f_magic[2]; /* magic number */ | ||
14 | char f_nscns[2]; /* number of sections */ | ||
15 | char f_timdat[4]; /* time & date stamp */ | ||
16 | char f_symptr[4]; /* file pointer to symtab */ | ||
17 | char f_nsyms[4]; /* number of symtab entries */ | ||
18 | char f_opthdr[2]; /* sizeof(optional hdr) */ | ||
19 | char f_flags[2]; /* flags */ | ||
20 | }; | ||
21 | |||
22 | /* IBM RS/6000 */ | ||
23 | #define U802WRMAGIC 0730 /* writeable text segments **chh** */ | ||
24 | #define U802ROMAGIC 0735 /* readonly sharable text segments */ | ||
25 | #define U802TOCMAGIC 0737 /* readonly text segments and TOC */ | ||
26 | |||
27 | #define BADMAG(x) \ | ||
28 | ((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \ | ||
29 | (x).f_magic != U802TOCMAGIC) | ||
30 | |||
31 | #define FILHDR struct external_filehdr | ||
32 | #define FILHSZ 20 | ||
33 | |||
34 | |||
35 | /********************** AOUT "OPTIONAL HEADER" **********************/ | ||
36 | |||
37 | |||
38 | typedef struct | ||
39 | { | ||
40 | unsigned char magic[2]; /* type of file */ | ||
41 | unsigned char vstamp[2]; /* version stamp */ | ||
42 | unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */ | ||
43 | unsigned char dsize[4]; /* initialized data " " */ | ||
44 | unsigned char bsize[4]; /* uninitialized data " " */ | ||
45 | unsigned char entry[4]; /* entry pt. */ | ||
46 | unsigned char text_start[4]; /* base of text used for this file */ | ||
47 | unsigned char data_start[4]; /* base of data used for this file */ | ||
48 | unsigned char o_toc[4]; /* address of TOC */ | ||
49 | unsigned char o_snentry[2]; /* section number of entry point */ | ||
50 | unsigned char o_sntext[2]; /* section number of .text section */ | ||
51 | unsigned char o_sndata[2]; /* section number of .data section */ | ||
52 | unsigned char o_sntoc[2]; /* section number of TOC */ | ||
53 | unsigned char o_snloader[2]; /* section number of .loader section */ | ||
54 | unsigned char o_snbss[2]; /* section number of .bss section */ | ||
55 | unsigned char o_algntext[2]; /* .text alignment */ | ||
56 | unsigned char o_algndata[2]; /* .data alignment */ | ||
57 | unsigned char o_modtype[2]; /* module type (??) */ | ||
58 | unsigned char o_cputype[2]; /* cpu type */ | ||
59 | unsigned char o_maxstack[4]; /* max stack size (??) */ | ||
60 | unsigned char o_maxdata[4]; /* max data size (??) */ | ||
61 | unsigned char o_resv2[12]; /* reserved */ | ||
62 | } | ||
63 | AOUTHDR; | ||
64 | |||
65 | #define AOUTSZ 72 | ||
66 | #define SMALL_AOUTSZ (28) | ||
67 | #define AOUTHDRSZ 72 | ||
68 | |||
69 | #define RS6K_AOUTHDR_OMAGIC 0x0107 /* old: text & data writeable */ | ||
70 | #define RS6K_AOUTHDR_NMAGIC 0x0108 /* new: text r/o, data r/w */ | ||
71 | #define RS6K_AOUTHDR_ZMAGIC 0x010B /* paged: text r/o, both page-aligned */ | ||
72 | |||
73 | |||
74 | /********************** SECTION HEADER **********************/ | ||
75 | |||
76 | |||
77 | struct external_scnhdr { | ||
78 | char s_name[8]; /* section name */ | ||
79 | char s_paddr[4]; /* physical address, aliased s_nlib */ | ||
80 | char s_vaddr[4]; /* virtual address */ | ||
81 | char s_size[4]; /* section size */ | ||
82 | char s_scnptr[4]; /* file ptr to raw data for section */ | ||
83 | char s_relptr[4]; /* file ptr to relocation */ | ||
84 | char s_lnnoptr[4]; /* file ptr to line numbers */ | ||
85 | char s_nreloc[2]; /* number of relocation entries */ | ||
86 | char s_nlnno[2]; /* number of line number entries*/ | ||
87 | char s_flags[4]; /* flags */ | ||
88 | }; | ||
89 | |||
90 | /* | ||
91 | * names of "special" sections | ||
92 | */ | ||
93 | #define _TEXT ".text" | ||
94 | #define _DATA ".data" | ||
95 | #define _BSS ".bss" | ||
96 | #define _PAD ".pad" | ||
97 | #define _LOADER ".loader" | ||
98 | |||
99 | #define SCNHDR struct external_scnhdr | ||
100 | #define SCNHSZ 40 | ||
101 | |||
102 | /* XCOFF uses a special .loader section with type STYP_LOADER. */ | ||
103 | #define STYP_LOADER 0x1000 | ||
104 | |||
105 | /* XCOFF uses a special .debug section with type STYP_DEBUG. */ | ||
106 | #define STYP_DEBUG 0x2000 | ||
107 | |||
108 | /* XCOFF handles line number or relocation overflow by creating | ||
109 | another section header with STYP_OVRFLO set. */ | ||
110 | #define STYP_OVRFLO 0x8000 | ||
111 | |||
112 | /********************** LINE NUMBERS **********************/ | ||
113 | |||
114 | /* 1 line number entry for every "breakpointable" source line in a section. | ||
115 | * Line numbers are grouped on a per function basis; first entry in a function | ||
116 | * grouping will have l_lnno = 0 and in place of physical address will be the | ||
117 | * symbol table index of the function name. | ||
118 | */ | ||
119 | struct external_lineno { | ||
120 | union { | ||
121 | char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/ | ||
122 | char l_paddr[4]; /* (physical) address of line number */ | ||
123 | } l_addr; | ||
124 | char l_lnno[2]; /* line number */ | ||
125 | }; | ||
126 | |||
127 | |||
128 | #define LINENO struct external_lineno | ||
129 | #define LINESZ 6 | ||
130 | |||
131 | |||
132 | /********************** SYMBOLS **********************/ | ||
133 | |||
134 | #define E_SYMNMLEN 8 /* # characters in a symbol name */ | ||
135 | #define E_FILNMLEN 14 /* # characters in a file name */ | ||
136 | #define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ | ||
137 | |||
138 | struct external_syment | ||
139 | { | ||
140 | union { | ||
141 | char e_name[E_SYMNMLEN]; | ||
142 | struct { | ||
143 | char e_zeroes[4]; | ||
144 | char e_offset[4]; | ||
145 | } e; | ||
146 | } e; | ||
147 | char e_value[4]; | ||
148 | char e_scnum[2]; | ||
149 | char e_type[2]; | ||
150 | char e_sclass[1]; | ||
151 | char e_numaux[1]; | ||
152 | }; | ||
153 | |||
154 | |||
155 | |||
156 | #define N_BTMASK (017) | ||
157 | #define N_TMASK (060) | ||
158 | #define N_BTSHFT (4) | ||
159 | #define N_TSHIFT (2) | ||
160 | |||
161 | |||
162 | union external_auxent { | ||
163 | struct { | ||
164 | char x_tagndx[4]; /* str, un, or enum tag indx */ | ||
165 | union { | ||
166 | struct { | ||
167 | char x_lnno[2]; /* declaration line number */ | ||
168 | char x_size[2]; /* str/union/array size */ | ||
169 | } x_lnsz; | ||
170 | char x_fsize[4]; /* size of function */ | ||
171 | } x_misc; | ||
172 | union { | ||
173 | struct { /* if ISFCN, tag, or .bb */ | ||
174 | char x_lnnoptr[4]; /* ptr to fcn line # */ | ||
175 | char x_endndx[4]; /* entry ndx past block end */ | ||
176 | } x_fcn; | ||
177 | struct { /* if ISARY, up to 4 dimen. */ | ||
178 | char x_dimen[E_DIMNUM][2]; | ||
179 | } x_ary; | ||
180 | } x_fcnary; | ||
181 | char x_tvndx[2]; /* tv index */ | ||
182 | } x_sym; | ||
183 | |||
184 | union { | ||
185 | char x_fname[E_FILNMLEN]; | ||
186 | struct { | ||
187 | char x_zeroes[4]; | ||
188 | char x_offset[4]; | ||
189 | } x_n; | ||
190 | } x_file; | ||
191 | |||
192 | struct { | ||
193 | char x_scnlen[4]; /* section length */ | ||
194 | char x_nreloc[2]; /* # relocation entries */ | ||
195 | char x_nlinno[2]; /* # line numbers */ | ||
196 | } x_scn; | ||
197 | |||
198 | struct { | ||
199 | char x_tvfill[4]; /* tv fill value */ | ||
200 | char x_tvlen[2]; /* length of .tv */ | ||
201 | char x_tvran[2][2]; /* tv range */ | ||
202 | } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ | ||
203 | |||
204 | struct { | ||
205 | unsigned char x_scnlen[4]; | ||
206 | unsigned char x_parmhash[4]; | ||
207 | unsigned char x_snhash[2]; | ||
208 | unsigned char x_smtyp[1]; | ||
209 | unsigned char x_smclas[1]; | ||
210 | unsigned char x_stab[4]; | ||
211 | unsigned char x_snstab[2]; | ||
212 | } x_csect; | ||
213 | |||
214 | }; | ||
215 | |||
216 | #define SYMENT struct external_syment | ||
217 | #define SYMESZ 18 | ||
218 | #define AUXENT union external_auxent | ||
219 | #define AUXESZ 18 | ||
220 | #define DBXMASK 0x80 /* for dbx storage mask */ | ||
221 | #define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK) | ||
222 | |||
223 | |||
224 | |||
225 | /********************** RELOCATION DIRECTIVES **********************/ | ||
226 | |||
227 | |||
228 | struct external_reloc { | ||
229 | char r_vaddr[4]; | ||
230 | char r_symndx[4]; | ||
231 | char r_size[1]; | ||
232 | char r_type[1]; | ||
233 | }; | ||
234 | |||
235 | |||
236 | #define RELOC struct external_reloc | ||
237 | #define RELSZ 10 | ||
238 | |||
239 | #define DEFAULT_DATA_SECTION_ALIGNMENT 4 | ||
240 | #define DEFAULT_BSS_SECTION_ALIGNMENT 4 | ||
241 | #define DEFAULT_TEXT_SECTION_ALIGNMENT 4 | ||
242 | /* For new sections we havn't heard of before */ | ||
243 | #define DEFAULT_SECTION_ALIGNMENT 4 | ||
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c new file mode 100644 index 000000000000..b5aa522f8b77 --- /dev/null +++ b/arch/powerpc/boot/stdio.c | |||
@@ -0,0 +1,325 @@ | |||
1 | /* | ||
2 | * Copyright (C) Paul Mackerras 1997. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | #include <stdarg.h> | ||
10 | #include <stddef.h> | ||
11 | #include "string.h" | ||
12 | #include "stdio.h" | ||
13 | #include "prom.h" | ||
14 | |||
15 | size_t strnlen(const char * s, size_t count) | ||
16 | { | ||
17 | const char *sc; | ||
18 | |||
19 | for (sc = s; count-- && *sc != '\0'; ++sc) | ||
20 | /* nothing */; | ||
21 | return sc - s; | ||
22 | } | ||
23 | |||
24 | extern unsigned int __div64_32(unsigned long long *dividend, | ||
25 | unsigned int divisor); | ||
26 | |||
27 | /* The unnecessary pointer compare is there | ||
28 | * to check for type safety (n must be 64bit) | ||
29 | */ | ||
30 | # define do_div(n,base) ({ \ | ||
31 | unsigned int __base = (base); \ | ||
32 | unsigned int __rem; \ | ||
33 | (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \ | ||
34 | if (((n) >> 32) == 0) { \ | ||
35 | __rem = (unsigned int)(n) % __base; \ | ||
36 | (n) = (unsigned int)(n) / __base; \ | ||
37 | } else \ | ||
38 | __rem = __div64_32(&(n), __base); \ | ||
39 | __rem; \ | ||
40 | }) | ||
41 | |||
42 | static int skip_atoi(const char **s) | ||
43 | { | ||
44 | int i, c; | ||
45 | |||
46 | for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s) | ||
47 | i = i*10 + c - '0'; | ||
48 | return i; | ||
49 | } | ||
50 | |||
51 | #define ZEROPAD 1 /* pad with zero */ | ||
52 | #define SIGN 2 /* unsigned/signed long */ | ||
53 | #define PLUS 4 /* show plus */ | ||
54 | #define SPACE 8 /* space if plus */ | ||
55 | #define LEFT 16 /* left justified */ | ||
56 | #define SPECIAL 32 /* 0x */ | ||
57 | #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ | ||
58 | |||
59 | static char * number(char * str, unsigned long long num, int base, int size, int precision, int type) | ||
60 | { | ||
61 | char c,sign,tmp[66]; | ||
62 | const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; | ||
63 | int i; | ||
64 | |||
65 | if (type & LARGE) | ||
66 | digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | ||
67 | if (type & LEFT) | ||
68 | type &= ~ZEROPAD; | ||
69 | if (base < 2 || base > 36) | ||
70 | return 0; | ||
71 | c = (type & ZEROPAD) ? '0' : ' '; | ||
72 | sign = 0; | ||
73 | if (type & SIGN) { | ||
74 | if ((signed long long)num < 0) { | ||
75 | sign = '-'; | ||
76 | num = - (signed long long)num; | ||
77 | size--; | ||
78 | } else if (type & PLUS) { | ||
79 | sign = '+'; | ||
80 | size--; | ||
81 | } else if (type & SPACE) { | ||
82 | sign = ' '; | ||
83 | size--; | ||
84 | } | ||
85 | } | ||
86 | if (type & SPECIAL) { | ||
87 | if (base == 16) | ||
88 | size -= 2; | ||
89 | else if (base == 8) | ||
90 | size--; | ||
91 | } | ||
92 | i = 0; | ||
93 | if (num == 0) | ||
94 | tmp[i++]='0'; | ||
95 | else while (num != 0) { | ||
96 | tmp[i++] = digits[do_div(num, base)]; | ||
97 | } | ||
98 | if (i > precision) | ||
99 | precision = i; | ||
100 | size -= precision; | ||
101 | if (!(type&(ZEROPAD+LEFT))) | ||
102 | while(size-->0) | ||
103 | *str++ = ' '; | ||
104 | if (sign) | ||
105 | *str++ = sign; | ||
106 | if (type & SPECIAL) { | ||
107 | if (base==8) | ||
108 | *str++ = '0'; | ||
109 | else if (base==16) { | ||
110 | *str++ = '0'; | ||
111 | *str++ = digits[33]; | ||
112 | } | ||
113 | } | ||
114 | if (!(type & LEFT)) | ||
115 | while (size-- > 0) | ||
116 | *str++ = c; | ||
117 | while (i < precision--) | ||
118 | *str++ = '0'; | ||
119 | while (i-- > 0) | ||
120 | *str++ = tmp[i]; | ||
121 | while (size-- > 0) | ||
122 | *str++ = ' '; | ||
123 | return str; | ||
124 | } | ||
125 | |||
126 | int vsprintf(char *buf, const char *fmt, va_list args) | ||
127 | { | ||
128 | int len; | ||
129 | unsigned long long num; | ||
130 | int i, base; | ||
131 | char * str; | ||
132 | const char *s; | ||
133 | |||
134 | int flags; /* flags to number() */ | ||
135 | |||
136 | int field_width; /* width of output field */ | ||
137 | int precision; /* min. # of digits for integers; max | ||
138 | number of chars for from string */ | ||
139 | int qualifier; /* 'h', 'l', or 'L' for integer fields */ | ||
140 | /* 'z' support added 23/7/1999 S.H. */ | ||
141 | /* 'z' changed to 'Z' --davidm 1/25/99 */ | ||
142 | |||
143 | |||
144 | for (str=buf ; *fmt ; ++fmt) { | ||
145 | if (*fmt != '%') { | ||
146 | *str++ = *fmt; | ||
147 | continue; | ||
148 | } | ||
149 | |||
150 | /* process flags */ | ||
151 | flags = 0; | ||
152 | repeat: | ||
153 | ++fmt; /* this also skips first '%' */ | ||
154 | switch (*fmt) { | ||
155 | case '-': flags |= LEFT; goto repeat; | ||
156 | case '+': flags |= PLUS; goto repeat; | ||
157 | case ' ': flags |= SPACE; goto repeat; | ||
158 | case '#': flags |= SPECIAL; goto repeat; | ||
159 | case '0': flags |= ZEROPAD; goto repeat; | ||
160 | } | ||
161 | |||
162 | /* get field width */ | ||
163 | field_width = -1; | ||
164 | if ('0' <= *fmt && *fmt <= '9') | ||
165 | field_width = skip_atoi(&fmt); | ||
166 | else if (*fmt == '*') { | ||
167 | ++fmt; | ||
168 | /* it's the next argument */ | ||
169 | field_width = va_arg(args, int); | ||
170 | if (field_width < 0) { | ||
171 | field_width = -field_width; | ||
172 | flags |= LEFT; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | /* get the precision */ | ||
177 | precision = -1; | ||
178 | if (*fmt == '.') { | ||
179 | ++fmt; | ||
180 | if ('0' <= *fmt && *fmt <= '9') | ||
181 | precision = skip_atoi(&fmt); | ||
182 | else if (*fmt == '*') { | ||
183 | ++fmt; | ||
184 | /* it's the next argument */ | ||
185 | precision = va_arg(args, int); | ||
186 | } | ||
187 | if (precision < 0) | ||
188 | precision = 0; | ||
189 | } | ||
190 | |||
191 | /* get the conversion qualifier */ | ||
192 | qualifier = -1; | ||
193 | if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { | ||
194 | qualifier = *fmt; | ||
195 | ++fmt; | ||
196 | } | ||
197 | |||
198 | /* default base */ | ||
199 | base = 10; | ||
200 | |||
201 | switch (*fmt) { | ||
202 | case 'c': | ||
203 | if (!(flags & LEFT)) | ||
204 | while (--field_width > 0) | ||
205 | *str++ = ' '; | ||
206 | *str++ = (unsigned char) va_arg(args, int); | ||
207 | while (--field_width > 0) | ||
208 | *str++ = ' '; | ||
209 | continue; | ||
210 | |||
211 | case 's': | ||
212 | s = va_arg(args, char *); | ||
213 | if (!s) | ||
214 | s = "<NULL>"; | ||
215 | |||
216 | len = strnlen(s, precision); | ||
217 | |||
218 | if (!(flags & LEFT)) | ||
219 | while (len < field_width--) | ||
220 | *str++ = ' '; | ||
221 | for (i = 0; i < len; ++i) | ||
222 | *str++ = *s++; | ||
223 | while (len < field_width--) | ||
224 | *str++ = ' '; | ||
225 | continue; | ||
226 | |||
227 | case 'p': | ||
228 | if (field_width == -1) { | ||
229 | field_width = 2*sizeof(void *); | ||
230 | flags |= ZEROPAD; | ||
231 | } | ||
232 | str = number(str, | ||
233 | (unsigned long) va_arg(args, void *), 16, | ||
234 | field_width, precision, flags); | ||
235 | continue; | ||
236 | |||
237 | |||
238 | case 'n': | ||
239 | if (qualifier == 'l') { | ||
240 | long * ip = va_arg(args, long *); | ||
241 | *ip = (str - buf); | ||
242 | } else if (qualifier == 'Z') { | ||
243 | size_t * ip = va_arg(args, size_t *); | ||
244 | *ip = (str - buf); | ||
245 | } else { | ||
246 | int * ip = va_arg(args, int *); | ||
247 | *ip = (str - buf); | ||
248 | } | ||
249 | continue; | ||
250 | |||
251 | case '%': | ||
252 | *str++ = '%'; | ||
253 | continue; | ||
254 | |||
255 | /* integer number formats - set up the flags and "break" */ | ||
256 | case 'o': | ||
257 | base = 8; | ||
258 | break; | ||
259 | |||
260 | case 'X': | ||
261 | flags |= LARGE; | ||
262 | case 'x': | ||
263 | base = 16; | ||
264 | break; | ||
265 | |||
266 | case 'd': | ||
267 | case 'i': | ||
268 | flags |= SIGN; | ||
269 | case 'u': | ||
270 | break; | ||
271 | |||
272 | default: | ||
273 | *str++ = '%'; | ||
274 | if (*fmt) | ||
275 | *str++ = *fmt; | ||
276 | else | ||
277 | --fmt; | ||
278 | continue; | ||
279 | } | ||
280 | if (qualifier == 'l') { | ||
281 | num = va_arg(args, unsigned long); | ||
282 | if (flags & SIGN) | ||
283 | num = (signed long) num; | ||
284 | } else if (qualifier == 'Z') { | ||
285 | num = va_arg(args, size_t); | ||
286 | } else if (qualifier == 'h') { | ||
287 | num = (unsigned short) va_arg(args, int); | ||
288 | if (flags & SIGN) | ||
289 | num = (signed short) num; | ||
290 | } else { | ||
291 | num = va_arg(args, unsigned int); | ||
292 | if (flags & SIGN) | ||
293 | num = (signed int) num; | ||
294 | } | ||
295 | str = number(str, num, base, field_width, precision, flags); | ||
296 | } | ||
297 | *str = '\0'; | ||
298 | return str-buf; | ||
299 | } | ||
300 | |||
301 | int sprintf(char * buf, const char *fmt, ...) | ||
302 | { | ||
303 | va_list args; | ||
304 | int i; | ||
305 | |||
306 | va_start(args, fmt); | ||
307 | i=vsprintf(buf,fmt,args); | ||
308 | va_end(args); | ||
309 | return i; | ||
310 | } | ||
311 | |||
312 | static char sprint_buf[1024]; | ||
313 | |||
314 | int | ||
315 | printf(const char *fmt, ...) | ||
316 | { | ||
317 | va_list args; | ||
318 | int n; | ||
319 | |||
320 | va_start(args, fmt); | ||
321 | n = vsprintf(sprint_buf, fmt, args); | ||
322 | va_end(args); | ||
323 | write(stdout, sprint_buf, n); | ||
324 | return n; | ||
325 | } | ||
diff --git a/arch/powerpc/boot/stdio.h b/arch/powerpc/boot/stdio.h index 24bd3a8dee94..eb9e16c87aef 100644 --- a/arch/powerpc/boot/stdio.h +++ b/arch/powerpc/boot/stdio.h | |||
@@ -7,10 +7,4 @@ extern int sprintf(char *buf, const char *fmt, ...); | |||
7 | 7 | ||
8 | extern int vsprintf(char *buf, const char *fmt, va_list args); | 8 | extern int vsprintf(char *buf, const char *fmt, va_list args); |
9 | 9 | ||
10 | extern int putc(int c, void *f); | ||
11 | extern int putchar(int c); | ||
12 | extern int getchar(void); | ||
13 | |||
14 | extern int fputs(char *str, void *f); | ||
15 | |||
16 | #endif /* _PPC_BOOT_STDIO_H_ */ | 10 | #endif /* _PPC_BOOT_STDIO_H_ */ |
diff --git a/arch/powerpc/boot/string.S b/arch/powerpc/boot/string.S index b1eeaed7db17..ac3d43b6a324 100644 --- a/arch/powerpc/boot/string.S +++ b/arch/powerpc/boot/string.S | |||
@@ -107,10 +107,12 @@ memcpy: | |||
107 | rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */ | 107 | rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */ |
108 | addi r6,r3,-4 | 108 | addi r6,r3,-4 |
109 | addi r4,r4,-4 | 109 | addi r4,r4,-4 |
110 | beq 2f /* if less than 8 bytes to do */ | 110 | beq 3f /* if less than 8 bytes to do */ |
111 | andi. r0,r6,3 /* get dest word aligned */ | 111 | andi. r0,r6,3 /* get dest word aligned */ |
112 | mtctr r7 | 112 | mtctr r7 |
113 | bne 5f | 113 | bne 5f |
114 | andi. r0,r4,3 /* check src word aligned too */ | ||
115 | bne 3f | ||
114 | 1: lwz r7,4(r4) | 116 | 1: lwz r7,4(r4) |
115 | lwzu r8,8(r4) | 117 | lwzu r8,8(r4) |
116 | stw r7,4(r6) | 118 | stw r7,4(r6) |
@@ -132,6 +134,11 @@ memcpy: | |||
132 | bdnz 4b | 134 | bdnz 4b |
133 | blr | 135 | blr |
134 | 5: subfic r0,r0,4 | 136 | 5: subfic r0,r0,4 |
137 | cmpw cr1,r0,r5 | ||
138 | add r7,r0,r4 | ||
139 | andi. r7,r7,3 /* will source be word-aligned too? */ | ||
140 | ble cr1,3b | ||
141 | bne 3b /* do byte-by-byte if not */ | ||
135 | mtctr r0 | 142 | mtctr r0 |
136 | 6: lbz r7,4(r4) | 143 | 6: lbz r7,4(r4) |
137 | addi r4,r4,1 | 144 | addi r4,r4,1 |
@@ -149,10 +156,12 @@ backwards_memcpy: | |||
149 | rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */ | 156 | rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */ |
150 | add r6,r3,r5 | 157 | add r6,r3,r5 |
151 | add r4,r4,r5 | 158 | add r4,r4,r5 |
152 | beq 2f | 159 | beq 3f |
153 | andi. r0,r6,3 | 160 | andi. r0,r6,3 |
154 | mtctr r7 | 161 | mtctr r7 |
155 | bne 5f | 162 | bne 5f |
163 | andi. r0,r4,3 | ||
164 | bne 3f | ||
156 | 1: lwz r7,-4(r4) | 165 | 1: lwz r7,-4(r4) |
157 | lwzu r8,-8(r4) | 166 | lwzu r8,-8(r4) |
158 | stw r7,-4(r6) | 167 | stw r7,-4(r6) |
@@ -171,7 +180,12 @@ backwards_memcpy: | |||
171 | stbu r0,-1(r6) | 180 | stbu r0,-1(r6) |
172 | bdnz 4b | 181 | bdnz 4b |
173 | blr | 182 | blr |
174 | 5: mtctr r0 | 183 | 5: cmpw cr1,r0,r5 |
184 | subf r7,r0,r4 | ||
185 | andi. r7,r7,3 | ||
186 | ble cr1,3b | ||
187 | bne 3b | ||
188 | mtctr r0 | ||
175 | 6: lbzu r7,-1(r4) | 189 | 6: lbzu r7,-1(r4) |
176 | stbu r7,-1(r6) | 190 | stbu r7,-1(r6) |
177 | bdnz 6b | 191 | bdnz 6b |
diff --git a/arch/powerpc/boot/zImage.coff.lds b/arch/powerpc/boot/zImage.coff.lds new file mode 100644 index 000000000000..6016251a1a2c --- /dev/null +++ b/arch/powerpc/boot/zImage.coff.lds | |||
@@ -0,0 +1,46 @@ | |||
1 | OUTPUT_ARCH(powerpc:common) | ||
2 | ENTRY(_start) | ||
3 | SECTIONS | ||
4 | { | ||
5 | . = (5*1024*1024); | ||
6 | _start = .; | ||
7 | .text : | ||
8 | { | ||
9 | *(.text) | ||
10 | *(.fixup) | ||
11 | } | ||
12 | _etext = .; | ||
13 | . = ALIGN(4096); | ||
14 | .data : | ||
15 | { | ||
16 | *(.rodata*) | ||
17 | *(.data*) | ||
18 | *(.sdata*) | ||
19 | __got2_start = .; | ||
20 | *(.got2) | ||
21 | __got2_end = .; | ||
22 | |||
23 | _vmlinux_start = .; | ||
24 | *(.kernel:vmlinux.strip) | ||
25 | _vmlinux_end = .; | ||
26 | |||
27 | _initrd_start = .; | ||
28 | *(.kernel:initrd) | ||
29 | _initrd_end = .; | ||
30 | } | ||
31 | |||
32 | . = ALIGN(4096); | ||
33 | _edata = .; | ||
34 | __bss_start = .; | ||
35 | .bss : | ||
36 | { | ||
37 | *(.sbss) | ||
38 | *(.bss) | ||
39 | } | ||
40 | _end = . ; | ||
41 | |||
42 | /DISCARD/ : | ||
43 | { | ||
44 | *(.comment) | ||
45 | } | ||
46 | } | ||
diff --git a/arch/powerpc/configs/mpc834x_sys_defconfig b/arch/powerpc/configs/mpc834x_sys_defconfig new file mode 100644 index 000000000000..3bff761965c2 --- /dev/null +++ b/arch/powerpc/configs/mpc834x_sys_defconfig | |||
@@ -0,0 +1,911 @@ | |||
1 | # | ||
2 | # Automatically generated make config: don't edit | ||
3 | # Linux kernel version: 2.6.15-g461d4edf-dirty | ||
4 | # Fri Jan 13 11:01:47 2006 | ||
5 | # | ||
6 | # CONFIG_PPC64 is not set | ||
7 | CONFIG_PPC32=y | ||
8 | CONFIG_PPC_MERGE=y | ||
9 | CONFIG_MMU=y | ||
10 | CONFIG_GENERIC_HARDIRQS=y | ||
11 | CONFIG_RWSEM_XCHGADD_ALGORITHM=y | ||
12 | CONFIG_GENERIC_CALIBRATE_DELAY=y | ||
13 | CONFIG_PPC=y | ||
14 | CONFIG_EARLY_PRINTK=y | ||
15 | CONFIG_GENERIC_NVRAM=y | ||
16 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y | ||
17 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y | ||
18 | CONFIG_PPC_OF=y | ||
19 | CONFIG_PPC_UDBG_16550=y | ||
20 | # CONFIG_GENERIC_TBSYNC is not set | ||
21 | CONFIG_DEFAULT_UIMAGE=y | ||
22 | |||
23 | # | ||
24 | # Processor support | ||
25 | # | ||
26 | # CONFIG_CLASSIC32 is not set | ||
27 | # CONFIG_PPC_52xx is not set | ||
28 | # CONFIG_PPC_82xx is not set | ||
29 | CONFIG_PPC_83xx=y | ||
30 | # CONFIG_40x is not set | ||
31 | # CONFIG_44x is not set | ||
32 | # CONFIG_8xx is not set | ||
33 | # CONFIG_E200 is not set | ||
34 | # CONFIG_E500 is not set | ||
35 | CONFIG_6xx=y | ||
36 | CONFIG_83xx=y | ||
37 | CONFIG_PPC_FPU=y | ||
38 | CONFIG_PPC_STD_MMU=y | ||
39 | CONFIG_PPC_STD_MMU_32=y | ||
40 | # CONFIG_SMP is not set | ||
41 | |||
42 | # | ||
43 | # Code maturity level options | ||
44 | # | ||
45 | CONFIG_EXPERIMENTAL=y | ||
46 | CONFIG_CLEAN_COMPILE=y | ||
47 | CONFIG_BROKEN_ON_SMP=y | ||
48 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
49 | |||
50 | # | ||
51 | # General setup | ||
52 | # | ||
53 | CONFIG_LOCALVERSION="" | ||
54 | CONFIG_LOCALVERSION_AUTO=y | ||
55 | CONFIG_SWAP=y | ||
56 | CONFIG_SYSVIPC=y | ||
57 | # CONFIG_POSIX_MQUEUE is not set | ||
58 | # CONFIG_BSD_PROCESS_ACCT is not set | ||
59 | CONFIG_SYSCTL=y | ||
60 | # CONFIG_AUDIT is not set | ||
61 | # CONFIG_IKCONFIG is not set | ||
62 | CONFIG_INITRAMFS_SOURCE="" | ||
63 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set | ||
64 | CONFIG_EMBEDDED=y | ||
65 | # CONFIG_KALLSYMS is not set | ||
66 | CONFIG_HOTPLUG=y | ||
67 | CONFIG_PRINTK=y | ||
68 | CONFIG_BUG=y | ||
69 | CONFIG_ELF_CORE=y | ||
70 | CONFIG_BASE_FULL=y | ||
71 | CONFIG_FUTEX=y | ||
72 | # CONFIG_EPOLL is not set | ||
73 | CONFIG_SHMEM=y | ||
74 | CONFIG_CC_ALIGN_FUNCTIONS=0 | ||
75 | CONFIG_CC_ALIGN_LABELS=0 | ||
76 | CONFIG_CC_ALIGN_LOOPS=0 | ||
77 | CONFIG_CC_ALIGN_JUMPS=0 | ||
78 | CONFIG_SLAB=y | ||
79 | # CONFIG_TINY_SHMEM is not set | ||
80 | CONFIG_BASE_SMALL=0 | ||
81 | # CONFIG_SLOB is not set | ||
82 | |||
83 | # | ||
84 | # Loadable module support | ||
85 | # | ||
86 | CONFIG_MODULES=y | ||
87 | CONFIG_MODULE_UNLOAD=y | ||
88 | # CONFIG_MODULE_FORCE_UNLOAD is not set | ||
89 | CONFIG_OBSOLETE_MODPARM=y | ||
90 | # CONFIG_MODVERSIONS is not set | ||
91 | # CONFIG_MODULE_SRCVERSION_ALL is not set | ||
92 | # CONFIG_KMOD is not set | ||
93 | |||
94 | # | ||
95 | # Block layer | ||
96 | # | ||
97 | # CONFIG_LBD is not set | ||
98 | |||
99 | # | ||
100 | # IO Schedulers | ||
101 | # | ||
102 | CONFIG_IOSCHED_NOOP=y | ||
103 | CONFIG_IOSCHED_AS=y | ||
104 | CONFIG_IOSCHED_DEADLINE=y | ||
105 | CONFIG_IOSCHED_CFQ=y | ||
106 | CONFIG_DEFAULT_AS=y | ||
107 | # CONFIG_DEFAULT_DEADLINE is not set | ||
108 | # CONFIG_DEFAULT_CFQ is not set | ||
109 | # CONFIG_DEFAULT_NOOP is not set | ||
110 | CONFIG_DEFAULT_IOSCHED="anticipatory" | ||
111 | CONFIG_PPC_GEN550=y | ||
112 | # CONFIG_WANT_EARLY_SERIAL is not set | ||
113 | |||
114 | # | ||
115 | # Platform support | ||
116 | # | ||
117 | CONFIG_MPC834x_SYS=y | ||
118 | CONFIG_MPC834x=y | ||
119 | |||
120 | # | ||
121 | # Kernel options | ||
122 | # | ||
123 | # CONFIG_HIGHMEM is not set | ||
124 | # CONFIG_HZ_100 is not set | ||
125 | CONFIG_HZ_250=y | ||
126 | # CONFIG_HZ_1000 is not set | ||
127 | CONFIG_HZ=250 | ||
128 | CONFIG_PREEMPT_NONE=y | ||
129 | # CONFIG_PREEMPT_VOLUNTARY is not set | ||
130 | # CONFIG_PREEMPT is not set | ||
131 | CONFIG_BINFMT_ELF=y | ||
132 | # CONFIG_BINFMT_MISC is not set | ||
133 | CONFIG_ARCH_FLATMEM_ENABLE=y | ||
134 | CONFIG_SELECT_MEMORY_MODEL=y | ||
135 | CONFIG_FLATMEM_MANUAL=y | ||
136 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
137 | # CONFIG_SPARSEMEM_MANUAL is not set | ||
138 | CONFIG_FLATMEM=y | ||
139 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
140 | # CONFIG_SPARSEMEM_STATIC is not set | ||
141 | CONFIG_SPLIT_PTLOCK_CPUS=4 | ||
142 | CONFIG_PROC_DEVICETREE=y | ||
143 | # CONFIG_CMDLINE_BOOL is not set | ||
144 | # CONFIG_PM is not set | ||
145 | # CONFIG_SOFTWARE_SUSPEND is not set | ||
146 | CONFIG_SECCOMP=y | ||
147 | CONFIG_ISA_DMA_API=y | ||
148 | |||
149 | # | ||
150 | # Bus options | ||
151 | # | ||
152 | CONFIG_GENERIC_ISA_DMA=y | ||
153 | # CONFIG_PPC_I8259 is not set | ||
154 | CONFIG_PPC_INDIRECT_PCI=y | ||
155 | CONFIG_FSL_SOC=y | ||
156 | CONFIG_PCI=y | ||
157 | CONFIG_PCI_DOMAINS=y | ||
158 | # CONFIG_PCI_LEGACY_PROC is not set | ||
159 | |||
160 | # | ||
161 | # PCCARD (PCMCIA/CardBus) support | ||
162 | # | ||
163 | # CONFIG_PCCARD is not set | ||
164 | |||
165 | # | ||
166 | # PCI Hotplug Support | ||
167 | # | ||
168 | # CONFIG_HOTPLUG_PCI is not set | ||
169 | |||
170 | # | ||
171 | # Advanced setup | ||
172 | # | ||
173 | # CONFIG_ADVANCED_OPTIONS is not set | ||
174 | |||
175 | # | ||
176 | # Default settings for advanced configuration options are used | ||
177 | # | ||
178 | CONFIG_HIGHMEM_START=0xfe000000 | ||
179 | CONFIG_LOWMEM_SIZE=0x30000000 | ||
180 | CONFIG_KERNEL_START=0xc0000000 | ||
181 | CONFIG_TASK_SIZE=0x80000000 | ||
182 | CONFIG_BOOT_LOAD=0x00800000 | ||
183 | |||
184 | # | ||
185 | # Networking | ||
186 | # | ||
187 | CONFIG_NET=y | ||
188 | |||
189 | # | ||
190 | # Networking options | ||
191 | # | ||
192 | CONFIG_PACKET=y | ||
193 | # CONFIG_PACKET_MMAP is not set | ||
194 | CONFIG_UNIX=y | ||
195 | # CONFIG_NET_KEY is not set | ||
196 | CONFIG_INET=y | ||
197 | CONFIG_IP_MULTICAST=y | ||
198 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
199 | CONFIG_IP_FIB_HASH=y | ||
200 | CONFIG_IP_PNP=y | ||
201 | CONFIG_IP_PNP_DHCP=y | ||
202 | CONFIG_IP_PNP_BOOTP=y | ||
203 | # CONFIG_IP_PNP_RARP is not set | ||
204 | # CONFIG_NET_IPIP is not set | ||
205 | # CONFIG_NET_IPGRE is not set | ||
206 | # CONFIG_IP_MROUTE is not set | ||
207 | # CONFIG_ARPD is not set | ||
208 | CONFIG_SYN_COOKIES=y | ||
209 | # CONFIG_INET_AH is not set | ||
210 | # CONFIG_INET_ESP is not set | ||
211 | # CONFIG_INET_IPCOMP is not set | ||
212 | # CONFIG_INET_TUNNEL is not set | ||
213 | CONFIG_INET_DIAG=y | ||
214 | CONFIG_INET_TCP_DIAG=y | ||
215 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
216 | CONFIG_TCP_CONG_BIC=y | ||
217 | # CONFIG_IPV6 is not set | ||
218 | # CONFIG_NETFILTER is not set | ||
219 | |||
220 | # | ||
221 | # DCCP Configuration (EXPERIMENTAL) | ||
222 | # | ||
223 | # CONFIG_IP_DCCP is not set | ||
224 | |||
225 | # | ||
226 | # SCTP Configuration (EXPERIMENTAL) | ||
227 | # | ||
228 | # CONFIG_IP_SCTP is not set | ||
229 | # CONFIG_ATM is not set | ||
230 | # CONFIG_BRIDGE is not set | ||
231 | # CONFIG_VLAN_8021Q is not set | ||
232 | # CONFIG_DECNET is not set | ||
233 | # CONFIG_LLC2 is not set | ||
234 | # CONFIG_IPX is not set | ||
235 | # CONFIG_ATALK is not set | ||
236 | # CONFIG_X25 is not set | ||
237 | # CONFIG_LAPB is not set | ||
238 | # CONFIG_NET_DIVERT is not set | ||
239 | # CONFIG_ECONET is not set | ||
240 | # CONFIG_WAN_ROUTER is not set | ||
241 | |||
242 | # | ||
243 | # QoS and/or fair queueing | ||
244 | # | ||
245 | # CONFIG_NET_SCHED is not set | ||
246 | |||
247 | # | ||
248 | # Network testing | ||
249 | # | ||
250 | # CONFIG_NET_PKTGEN is not set | ||
251 | # CONFIG_HAMRADIO is not set | ||
252 | # CONFIG_IRDA is not set | ||
253 | # CONFIG_BT is not set | ||
254 | # CONFIG_IEEE80211 is not set | ||
255 | |||
256 | # | ||
257 | # Device Drivers | ||
258 | # | ||
259 | |||
260 | # | ||
261 | # Generic Driver Options | ||
262 | # | ||
263 | CONFIG_STANDALONE=y | ||
264 | CONFIG_PREVENT_FIRMWARE_BUILD=y | ||
265 | # CONFIG_FW_LOADER is not set | ||
266 | |||
267 | # | ||
268 | # Connector - unified userspace <-> kernelspace linker | ||
269 | # | ||
270 | # CONFIG_CONNECTOR is not set | ||
271 | |||
272 | # | ||
273 | # Memory Technology Devices (MTD) | ||
274 | # | ||
275 | # CONFIG_MTD is not set | ||
276 | |||
277 | # | ||
278 | # Parallel port support | ||
279 | # | ||
280 | # CONFIG_PARPORT is not set | ||
281 | |||
282 | # | ||
283 | # Plug and Play support | ||
284 | # | ||
285 | |||
286 | # | ||
287 | # Block devices | ||
288 | # | ||
289 | # CONFIG_BLK_DEV_FD is not set | ||
290 | # CONFIG_BLK_CPQ_DA is not set | ||
291 | # CONFIG_BLK_CPQ_CISS_DA is not set | ||
292 | # CONFIG_BLK_DEV_DAC960 is not set | ||
293 | # CONFIG_BLK_DEV_UMEM is not set | ||
294 | # CONFIG_BLK_DEV_COW_COMMON is not set | ||
295 | CONFIG_BLK_DEV_LOOP=y | ||
296 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set | ||
297 | # CONFIG_BLK_DEV_NBD is not set | ||
298 | # CONFIG_BLK_DEV_SX8 is not set | ||
299 | CONFIG_BLK_DEV_RAM=y | ||
300 | CONFIG_BLK_DEV_RAM_COUNT=16 | ||
301 | CONFIG_BLK_DEV_RAM_SIZE=32768 | ||
302 | CONFIG_BLK_DEV_INITRD=y | ||
303 | # CONFIG_CDROM_PKTCDVD is not set | ||
304 | # CONFIG_ATA_OVER_ETH is not set | ||
305 | |||
306 | # | ||
307 | # ATA/ATAPI/MFM/RLL support | ||
308 | # | ||
309 | # CONFIG_IDE is not set | ||
310 | |||
311 | # | ||
312 | # SCSI device support | ||
313 | # | ||
314 | # CONFIG_RAID_ATTRS is not set | ||
315 | # CONFIG_SCSI is not set | ||
316 | |||
317 | # | ||
318 | # Multi-device support (RAID and LVM) | ||
319 | # | ||
320 | # CONFIG_MD is not set | ||
321 | |||
322 | # | ||
323 | # Fusion MPT device support | ||
324 | # | ||
325 | # CONFIG_FUSION is not set | ||
326 | |||
327 | # | ||
328 | # IEEE 1394 (FireWire) support | ||
329 | # | ||
330 | # CONFIG_IEEE1394 is not set | ||
331 | |||
332 | # | ||
333 | # I2O device support | ||
334 | # | ||
335 | # CONFIG_I2O is not set | ||
336 | |||
337 | # | ||
338 | # Macintosh device drivers | ||
339 | # | ||
340 | # CONFIG_WINDFARM is not set | ||
341 | |||
342 | # | ||
343 | # Network device support | ||
344 | # | ||
345 | CONFIG_NETDEVICES=y | ||
346 | # CONFIG_DUMMY is not set | ||
347 | # CONFIG_BONDING is not set | ||
348 | # CONFIG_EQUALIZER is not set | ||
349 | # CONFIG_TUN is not set | ||
350 | |||
351 | # | ||
352 | # ARCnet devices | ||
353 | # | ||
354 | # CONFIG_ARCNET is not set | ||
355 | |||
356 | # | ||
357 | # PHY device support | ||
358 | # | ||
359 | CONFIG_PHYLIB=y | ||
360 | |||
361 | # | ||
362 | # MII PHY device drivers | ||
363 | # | ||
364 | CONFIG_MARVELL_PHY=y | ||
365 | # CONFIG_DAVICOM_PHY is not set | ||
366 | # CONFIG_QSEMI_PHY is not set | ||
367 | # CONFIG_LXT_PHY is not set | ||
368 | # CONFIG_CICADA_PHY is not set | ||
369 | |||
370 | # | ||
371 | # Ethernet (10 or 100Mbit) | ||
372 | # | ||
373 | CONFIG_NET_ETHERNET=y | ||
374 | CONFIG_MII=y | ||
375 | # CONFIG_HAPPYMEAL is not set | ||
376 | # CONFIG_SUNGEM is not set | ||
377 | # CONFIG_CASSINI is not set | ||
378 | # CONFIG_NET_VENDOR_3COM is not set | ||
379 | |||
380 | # | ||
381 | # Tulip family network device support | ||
382 | # | ||
383 | # CONFIG_NET_TULIP is not set | ||
384 | # CONFIG_HP100 is not set | ||
385 | CONFIG_NET_PCI=y | ||
386 | # CONFIG_PCNET32 is not set | ||
387 | # CONFIG_AMD8111_ETH is not set | ||
388 | # CONFIG_ADAPTEC_STARFIRE is not set | ||
389 | # CONFIG_B44 is not set | ||
390 | # CONFIG_FORCEDETH is not set | ||
391 | # CONFIG_DGRS is not set | ||
392 | # CONFIG_EEPRO100 is not set | ||
393 | CONFIG_E100=y | ||
394 | # CONFIG_FEALNX is not set | ||
395 | # CONFIG_NATSEMI is not set | ||
396 | # CONFIG_NE2K_PCI is not set | ||
397 | # CONFIG_8139CP is not set | ||
398 | # CONFIG_8139TOO is not set | ||
399 | # CONFIG_SIS900 is not set | ||
400 | # CONFIG_EPIC100 is not set | ||
401 | # CONFIG_SUNDANCE is not set | ||
402 | # CONFIG_TLAN is not set | ||
403 | # CONFIG_VIA_RHINE is not set | ||
404 | |||
405 | # | ||
406 | # Ethernet (1000 Mbit) | ||
407 | # | ||
408 | # CONFIG_ACENIC is not set | ||
409 | # CONFIG_DL2K is not set | ||
410 | # CONFIG_E1000 is not set | ||
411 | # CONFIG_NS83820 is not set | ||
412 | # CONFIG_HAMACHI is not set | ||
413 | # CONFIG_YELLOWFIN is not set | ||
414 | # CONFIG_R8169 is not set | ||
415 | # CONFIG_SIS190 is not set | ||
416 | # CONFIG_SKGE is not set | ||
417 | # CONFIG_SKY2 is not set | ||
418 | # CONFIG_SK98LIN is not set | ||
419 | # CONFIG_VIA_VELOCITY is not set | ||
420 | # CONFIG_TIGON3 is not set | ||
421 | # CONFIG_BNX2 is not set | ||
422 | CONFIG_GIANFAR=y | ||
423 | # CONFIG_GFAR_NAPI is not set | ||
424 | |||
425 | # | ||
426 | # Ethernet (10000 Mbit) | ||
427 | # | ||
428 | # CONFIG_CHELSIO_T1 is not set | ||
429 | # CONFIG_IXGB is not set | ||
430 | # CONFIG_S2IO is not set | ||
431 | |||
432 | # | ||
433 | # Token Ring devices | ||
434 | # | ||
435 | # CONFIG_TR is not set | ||
436 | |||
437 | # | ||
438 | # Wireless LAN (non-hamradio) | ||
439 | # | ||
440 | # CONFIG_NET_RADIO is not set | ||
441 | |||
442 | # | ||
443 | # Wan interfaces | ||
444 | # | ||
445 | # CONFIG_WAN is not set | ||
446 | # CONFIG_FDDI is not set | ||
447 | # CONFIG_HIPPI is not set | ||
448 | # CONFIG_PPP is not set | ||
449 | # CONFIG_SLIP is not set | ||
450 | # CONFIG_SHAPER is not set | ||
451 | # CONFIG_NETCONSOLE is not set | ||
452 | # CONFIG_NETPOLL is not set | ||
453 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
454 | |||
455 | # | ||
456 | # ISDN subsystem | ||
457 | # | ||
458 | # CONFIG_ISDN is not set | ||
459 | |||
460 | # | ||
461 | # Telephony Support | ||
462 | # | ||
463 | # CONFIG_PHONE is not set | ||
464 | |||
465 | # | ||
466 | # Input device support | ||
467 | # | ||
468 | CONFIG_INPUT=y | ||
469 | |||
470 | # | ||
471 | # Userland interfaces | ||
472 | # | ||
473 | # CONFIG_INPUT_MOUSEDEV is not set | ||
474 | # CONFIG_INPUT_JOYDEV is not set | ||
475 | # CONFIG_INPUT_TSDEV is not set | ||
476 | # CONFIG_INPUT_EVDEV is not set | ||
477 | # CONFIG_INPUT_EVBUG is not set | ||
478 | |||
479 | # | ||
480 | # Input Device Drivers | ||
481 | # | ||
482 | # CONFIG_INPUT_KEYBOARD is not set | ||
483 | # CONFIG_INPUT_MOUSE is not set | ||
484 | # CONFIG_INPUT_JOYSTICK is not set | ||
485 | # CONFIG_INPUT_TOUCHSCREEN is not set | ||
486 | # CONFIG_INPUT_MISC is not set | ||
487 | |||
488 | # | ||
489 | # Hardware I/O ports | ||
490 | # | ||
491 | # CONFIG_SERIO is not set | ||
492 | # CONFIG_GAMEPORT is not set | ||
493 | |||
494 | # | ||
495 | # Character devices | ||
496 | # | ||
497 | # CONFIG_VT is not set | ||
498 | # CONFIG_SERIAL_NONSTANDARD is not set | ||
499 | |||
500 | # | ||
501 | # Serial drivers | ||
502 | # | ||
503 | CONFIG_SERIAL_8250=y | ||
504 | CONFIG_SERIAL_8250_CONSOLE=y | ||
505 | CONFIG_SERIAL_8250_NR_UARTS=4 | ||
506 | CONFIG_SERIAL_8250_RUNTIME_UARTS=4 | ||
507 | # CONFIG_SERIAL_8250_EXTENDED is not set | ||
508 | |||
509 | # | ||
510 | # Non-8250 serial port support | ||
511 | # | ||
512 | CONFIG_SERIAL_CORE=y | ||
513 | CONFIG_SERIAL_CORE_CONSOLE=y | ||
514 | CONFIG_UNIX98_PTYS=y | ||
515 | CONFIG_LEGACY_PTYS=y | ||
516 | CONFIG_LEGACY_PTY_COUNT=256 | ||
517 | |||
518 | # | ||
519 | # IPMI | ||
520 | # | ||
521 | # CONFIG_IPMI_HANDLER is not set | ||
522 | |||
523 | # | ||
524 | # Watchdog Cards | ||
525 | # | ||
526 | CONFIG_WATCHDOG=y | ||
527 | # CONFIG_WATCHDOG_NOWAYOUT is not set | ||
528 | |||
529 | # | ||
530 | # Watchdog Device Drivers | ||
531 | # | ||
532 | # CONFIG_SOFT_WATCHDOG is not set | ||
533 | CONFIG_83xx_WDT=y | ||
534 | |||
535 | # | ||
536 | # PCI-based Watchdog Cards | ||
537 | # | ||
538 | # CONFIG_PCIPCWATCHDOG is not set | ||
539 | # CONFIG_WDTPCI is not set | ||
540 | # CONFIG_NVRAM is not set | ||
541 | CONFIG_GEN_RTC=y | ||
542 | # CONFIG_GEN_RTC_X is not set | ||
543 | # CONFIG_DTLK is not set | ||
544 | # CONFIG_R3964 is not set | ||
545 | # CONFIG_APPLICOM is not set | ||
546 | |||
547 | # | ||
548 | # Ftape, the floppy tape device driver | ||
549 | # | ||
550 | # CONFIG_AGP is not set | ||
551 | # CONFIG_DRM is not set | ||
552 | # CONFIG_RAW_DRIVER is not set | ||
553 | |||
554 | # | ||
555 | # TPM devices | ||
556 | # | ||
557 | # CONFIG_TCG_TPM is not set | ||
558 | # CONFIG_TELCLOCK is not set | ||
559 | |||
560 | # | ||
561 | # I2C support | ||
562 | # | ||
563 | CONFIG_I2C=y | ||
564 | CONFIG_I2C_CHARDEV=y | ||
565 | |||
566 | # | ||
567 | # I2C Algorithms | ||
568 | # | ||
569 | # CONFIG_I2C_ALGOBIT is not set | ||
570 | # CONFIG_I2C_ALGOPCF is not set | ||
571 | # CONFIG_I2C_ALGOPCA is not set | ||
572 | |||
573 | # | ||
574 | # I2C Hardware Bus support | ||
575 | # | ||
576 | # CONFIG_I2C_ALI1535 is not set | ||
577 | # CONFIG_I2C_ALI1563 is not set | ||
578 | # CONFIG_I2C_ALI15X3 is not set | ||
579 | # CONFIG_I2C_AMD756 is not set | ||
580 | # CONFIG_I2C_AMD8111 is not set | ||
581 | # CONFIG_I2C_I801 is not set | ||
582 | # CONFIG_I2C_I810 is not set | ||
583 | # CONFIG_I2C_PIIX4 is not set | ||
584 | CONFIG_I2C_MPC=y | ||
585 | # CONFIG_I2C_NFORCE2 is not set | ||
586 | # CONFIG_I2C_PARPORT_LIGHT is not set | ||
587 | # CONFIG_I2C_PROSAVAGE is not set | ||
588 | # CONFIG_I2C_SAVAGE4 is not set | ||
589 | # CONFIG_SCx200_ACB is not set | ||
590 | # CONFIG_I2C_SIS5595 is not set | ||
591 | # CONFIG_I2C_SIS630 is not set | ||
592 | # CONFIG_I2C_SIS96X is not set | ||
593 | # CONFIG_I2C_STUB is not set | ||
594 | # CONFIG_I2C_VIA is not set | ||
595 | # CONFIG_I2C_VIAPRO is not set | ||
596 | # CONFIG_I2C_VOODOO3 is not set | ||
597 | # CONFIG_I2C_PCA_ISA is not set | ||
598 | |||
599 | # | ||
600 | # Miscellaneous I2C Chip support | ||
601 | # | ||
602 | # CONFIG_SENSORS_DS1337 is not set | ||
603 | # CONFIG_SENSORS_DS1374 is not set | ||
604 | # CONFIG_SENSORS_EEPROM is not set | ||
605 | # CONFIG_SENSORS_PCF8574 is not set | ||
606 | # CONFIG_SENSORS_PCA9539 is not set | ||
607 | # CONFIG_SENSORS_PCF8591 is not set | ||
608 | # CONFIG_SENSORS_RTC8564 is not set | ||
609 | # CONFIG_SENSORS_M41T00 is not set | ||
610 | # CONFIG_SENSORS_MAX6875 is not set | ||
611 | # CONFIG_RTC_X1205_I2C is not set | ||
612 | # CONFIG_I2C_DEBUG_CORE is not set | ||
613 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
614 | # CONFIG_I2C_DEBUG_BUS is not set | ||
615 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
616 | |||
617 | # | ||
618 | # Dallas's 1-wire bus | ||
619 | # | ||
620 | # CONFIG_W1 is not set | ||
621 | |||
622 | # | ||
623 | # Hardware Monitoring support | ||
624 | # | ||
625 | CONFIG_HWMON=y | ||
626 | # CONFIG_HWMON_VID is not set | ||
627 | # CONFIG_SENSORS_ADM1021 is not set | ||
628 | # CONFIG_SENSORS_ADM1025 is not set | ||
629 | # CONFIG_SENSORS_ADM1026 is not set | ||
630 | # CONFIG_SENSORS_ADM1031 is not set | ||
631 | # CONFIG_SENSORS_ADM9240 is not set | ||
632 | # CONFIG_SENSORS_ASB100 is not set | ||
633 | # CONFIG_SENSORS_ATXP1 is not set | ||
634 | # CONFIG_SENSORS_DS1621 is not set | ||
635 | # CONFIG_SENSORS_FSCHER is not set | ||
636 | # CONFIG_SENSORS_FSCPOS is not set | ||
637 | # CONFIG_SENSORS_GL518SM is not set | ||
638 | # CONFIG_SENSORS_GL520SM is not set | ||
639 | # CONFIG_SENSORS_IT87 is not set | ||
640 | # CONFIG_SENSORS_LM63 is not set | ||
641 | # CONFIG_SENSORS_LM75 is not set | ||
642 | # CONFIG_SENSORS_LM77 is not set | ||
643 | # CONFIG_SENSORS_LM78 is not set | ||
644 | # CONFIG_SENSORS_LM80 is not set | ||
645 | # CONFIG_SENSORS_LM83 is not set | ||
646 | # CONFIG_SENSORS_LM85 is not set | ||
647 | # CONFIG_SENSORS_LM87 is not set | ||
648 | # CONFIG_SENSORS_LM90 is not set | ||
649 | # CONFIG_SENSORS_LM92 is not set | ||
650 | # CONFIG_SENSORS_MAX1619 is not set | ||
651 | # CONFIG_SENSORS_PC87360 is not set | ||
652 | # CONFIG_SENSORS_SIS5595 is not set | ||
653 | # CONFIG_SENSORS_SMSC47M1 is not set | ||
654 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
655 | # CONFIG_SENSORS_VIA686A is not set | ||
656 | # CONFIG_SENSORS_VT8231 is not set | ||
657 | # CONFIG_SENSORS_W83781D is not set | ||
658 | # CONFIG_SENSORS_W83792D is not set | ||
659 | # CONFIG_SENSORS_W83L785TS is not set | ||
660 | # CONFIG_SENSORS_W83627HF is not set | ||
661 | # CONFIG_SENSORS_W83627EHF is not set | ||
662 | # CONFIG_HWMON_DEBUG_CHIP is not set | ||
663 | |||
664 | # | ||
665 | # Misc devices | ||
666 | # | ||
667 | |||
668 | # | ||
669 | # Multimedia Capabilities Port drivers | ||
670 | # | ||
671 | |||
672 | # | ||
673 | # Multimedia devices | ||
674 | # | ||
675 | # CONFIG_VIDEO_DEV is not set | ||
676 | |||
677 | # | ||
678 | # Digital Video Broadcasting Devices | ||
679 | # | ||
680 | # CONFIG_DVB is not set | ||
681 | |||
682 | # | ||
683 | # Graphics support | ||
684 | # | ||
685 | # CONFIG_FB is not set | ||
686 | |||
687 | # | ||
688 | # Sound | ||
689 | # | ||
690 | # CONFIG_SOUND is not set | ||
691 | |||
692 | # | ||
693 | # USB support | ||
694 | # | ||
695 | CONFIG_USB_ARCH_HAS_HCD=y | ||
696 | CONFIG_USB_ARCH_HAS_OHCI=y | ||
697 | # CONFIG_USB is not set | ||
698 | |||
699 | # | ||
700 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' | ||
701 | # | ||
702 | |||
703 | # | ||
704 | # USB Gadget Support | ||
705 | # | ||
706 | # CONFIG_USB_GADGET is not set | ||
707 | |||
708 | # | ||
709 | # MMC/SD Card support | ||
710 | # | ||
711 | # CONFIG_MMC is not set | ||
712 | |||
713 | # | ||
714 | # InfiniBand support | ||
715 | # | ||
716 | # CONFIG_INFINIBAND is not set | ||
717 | |||
718 | # | ||
719 | # SN Devices | ||
720 | # | ||
721 | |||
722 | # | ||
723 | # File systems | ||
724 | # | ||
725 | CONFIG_EXT2_FS=y | ||
726 | # CONFIG_EXT2_FS_XATTR is not set | ||
727 | # CONFIG_EXT2_FS_XIP is not set | ||
728 | CONFIG_EXT3_FS=y | ||
729 | CONFIG_EXT3_FS_XATTR=y | ||
730 | # CONFIG_EXT3_FS_POSIX_ACL is not set | ||
731 | # CONFIG_EXT3_FS_SECURITY is not set | ||
732 | CONFIG_JBD=y | ||
733 | # CONFIG_JBD_DEBUG is not set | ||
734 | CONFIG_FS_MBCACHE=y | ||
735 | # CONFIG_REISERFS_FS is not set | ||
736 | # CONFIG_JFS_FS is not set | ||
737 | # CONFIG_FS_POSIX_ACL is not set | ||
738 | # CONFIG_XFS_FS is not set | ||
739 | # CONFIG_OCFS2_FS is not set | ||
740 | # CONFIG_MINIX_FS is not set | ||
741 | # CONFIG_ROMFS_FS is not set | ||
742 | CONFIG_INOTIFY=y | ||
743 | # CONFIG_QUOTA is not set | ||
744 | CONFIG_DNOTIFY=y | ||
745 | # CONFIG_AUTOFS_FS is not set | ||
746 | # CONFIG_AUTOFS4_FS is not set | ||
747 | # CONFIG_FUSE_FS is not set | ||
748 | |||
749 | # | ||
750 | # CD-ROM/DVD Filesystems | ||
751 | # | ||
752 | # CONFIG_ISO9660_FS is not set | ||
753 | # CONFIG_UDF_FS is not set | ||
754 | |||
755 | # | ||
756 | # DOS/FAT/NT Filesystems | ||
757 | # | ||
758 | # CONFIG_MSDOS_FS is not set | ||
759 | # CONFIG_VFAT_FS is not set | ||
760 | # CONFIG_NTFS_FS is not set | ||
761 | |||
762 | # | ||
763 | # Pseudo filesystems | ||
764 | # | ||
765 | CONFIG_PROC_FS=y | ||
766 | CONFIG_PROC_KCORE=y | ||
767 | CONFIG_SYSFS=y | ||
768 | CONFIG_TMPFS=y | ||
769 | # CONFIG_HUGETLB_PAGE is not set | ||
770 | CONFIG_RAMFS=y | ||
771 | # CONFIG_RELAYFS_FS is not set | ||
772 | # CONFIG_CONFIGFS_FS is not set | ||
773 | |||
774 | # | ||
775 | # Miscellaneous filesystems | ||
776 | # | ||
777 | # CONFIG_ADFS_FS is not set | ||
778 | # CONFIG_AFFS_FS is not set | ||
779 | # CONFIG_HFS_FS is not set | ||
780 | # CONFIG_HFSPLUS_FS is not set | ||
781 | # CONFIG_BEFS_FS is not set | ||
782 | # CONFIG_BFS_FS is not set | ||
783 | # CONFIG_EFS_FS is not set | ||
784 | # CONFIG_CRAMFS is not set | ||
785 | # CONFIG_VXFS_FS is not set | ||
786 | # CONFIG_HPFS_FS is not set | ||
787 | # CONFIG_QNX4FS_FS is not set | ||
788 | # CONFIG_SYSV_FS is not set | ||
789 | # CONFIG_UFS_FS is not set | ||
790 | |||
791 | # | ||
792 | # Network File Systems | ||
793 | # | ||
794 | CONFIG_NFS_FS=y | ||
795 | CONFIG_NFS_V3=y | ||
796 | # CONFIG_NFS_V3_ACL is not set | ||
797 | CONFIG_NFS_V4=y | ||
798 | # CONFIG_NFS_DIRECTIO is not set | ||
799 | # CONFIG_NFSD is not set | ||
800 | CONFIG_ROOT_NFS=y | ||
801 | CONFIG_LOCKD=y | ||
802 | CONFIG_LOCKD_V4=y | ||
803 | CONFIG_NFS_COMMON=y | ||
804 | CONFIG_SUNRPC=y | ||
805 | CONFIG_SUNRPC_GSS=y | ||
806 | CONFIG_RPCSEC_GSS_KRB5=y | ||
807 | # CONFIG_RPCSEC_GSS_SPKM3 is not set | ||
808 | # CONFIG_SMB_FS is not set | ||
809 | # CONFIG_CIFS is not set | ||
810 | # CONFIG_NCP_FS is not set | ||
811 | # CONFIG_CODA_FS is not set | ||
812 | # CONFIG_AFS_FS is not set | ||
813 | # CONFIG_9P_FS is not set | ||
814 | |||
815 | # | ||
816 | # Partition Types | ||
817 | # | ||
818 | CONFIG_PARTITION_ADVANCED=y | ||
819 | # CONFIG_ACORN_PARTITION is not set | ||
820 | # CONFIG_OSF_PARTITION is not set | ||
821 | # CONFIG_AMIGA_PARTITION is not set | ||
822 | # CONFIG_ATARI_PARTITION is not set | ||
823 | # CONFIG_MAC_PARTITION is not set | ||
824 | # CONFIG_MSDOS_PARTITION is not set | ||
825 | # CONFIG_LDM_PARTITION is not set | ||
826 | # CONFIG_SGI_PARTITION is not set | ||
827 | # CONFIG_ULTRIX_PARTITION is not set | ||
828 | # CONFIG_SUN_PARTITION is not set | ||
829 | # CONFIG_EFI_PARTITION is not set | ||
830 | |||
831 | # | ||
832 | # Native Language Support | ||
833 | # | ||
834 | # CONFIG_NLS is not set | ||
835 | |||
836 | # | ||
837 | # Library routines | ||
838 | # | ||
839 | # CONFIG_CRC_CCITT is not set | ||
840 | # CONFIG_CRC16 is not set | ||
841 | CONFIG_CRC32=y | ||
842 | # CONFIG_LIBCRC32C is not set | ||
843 | |||
844 | # | ||
845 | # Instrumentation Support | ||
846 | # | ||
847 | # CONFIG_PROFILING is not set | ||
848 | |||
849 | # | ||
850 | # Kernel hacking | ||
851 | # | ||
852 | # CONFIG_PRINTK_TIME is not set | ||
853 | # CONFIG_MAGIC_SYSRQ is not set | ||
854 | # CONFIG_DEBUG_KERNEL is not set | ||
855 | CONFIG_LOG_BUF_SHIFT=14 | ||
856 | # CONFIG_BOOTX_TEXT is not set | ||
857 | # CONFIG_SERIAL_TEXT_DEBUG is not set | ||
858 | # CONFIG_PPC_EARLY_DEBUG_LPAR is not set | ||
859 | # CONFIG_PPC_EARLY_DEBUG_G5 is not set | ||
860 | # CONFIG_PPC_EARLY_DEBUG_RTAS is not set | ||
861 | # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set | ||
862 | # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set | ||
863 | |||
864 | # | ||
865 | # Security options | ||
866 | # | ||
867 | # CONFIG_KEYS is not set | ||
868 | # CONFIG_SECURITY is not set | ||
869 | |||
870 | # | ||
871 | # Cryptographic options | ||
872 | # | ||
873 | CONFIG_CRYPTO=y | ||
874 | # CONFIG_CRYPTO_HMAC is not set | ||
875 | # CONFIG_CRYPTO_NULL is not set | ||
876 | # CONFIG_CRYPTO_MD4 is not set | ||
877 | CONFIG_CRYPTO_MD5=y | ||
878 | # CONFIG_CRYPTO_SHA1 is not set | ||
879 | # CONFIG_CRYPTO_SHA256 is not set | ||
880 | # CONFIG_CRYPTO_SHA512 is not set | ||
881 | # CONFIG_CRYPTO_WP512 is not set | ||
882 | # CONFIG_CRYPTO_TGR192 is not set | ||
883 | CONFIG_CRYPTO_DES=y | ||
884 | # CONFIG_CRYPTO_BLOWFISH is not set | ||
885 | # CONFIG_CRYPTO_TWOFISH is not set | ||
886 | # CONFIG_CRYPTO_SERPENT is not set | ||
887 | # CONFIG_CRYPTO_AES is not set | ||
888 | # CONFIG_CRYPTO_CAST5 is not set | ||
889 | # CONFIG_CRYPTO_CAST6 is not set | ||
890 | # CONFIG_CRYPTO_TEA is not set | ||
891 | # CONFIG_CRYPTO_ARC4 is not set | ||
892 | # CONFIG_CRYPTO_KHAZAD is not set | ||
893 | # CONFIG_CRYPTO_ANUBIS is not set | ||
894 | # CONFIG_CRYPTO_DEFLATE is not set | ||
895 | # CONFIG_CRYPTO_MICHAEL_MIC is not set | ||
896 | # CONFIG_CRYPTO_CRC32C is not set | ||
897 | # CONFIG_CRYPTO_TEST is not set | ||
898 | |||
899 | # | ||
900 | # Hardware crypto devices | ||
901 | # | ||
902 | |||
903 | # | ||
904 | # SEC2.x Options | ||
905 | # | ||
906 | CONFIG_MPC8349E_SEC2x=y | ||
907 | |||
908 | # | ||
909 | # SEC2.x Test Options | ||
910 | # | ||
911 | CONFIG_MPC8349E_SEC2xTEST=y | ||
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 56399c5c931a..840aad43a98b 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -135,7 +135,7 @@ int main(void) | |||
135 | DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); | 135 | DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); |
136 | DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb)); | 136 | DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb)); |
137 | DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); | 137 | DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); |
138 | DEFINE(PACALPPACA, offsetof(struct paca_struct, lppaca)); | 138 | DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr)); |
139 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); | 139 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); |
140 | 140 | ||
141 | DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); | 141 | DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); |
diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S index cca942fe6115..b61d86e7ceb6 100644 --- a/arch/powerpc/kernel/cpu_setup_power4.S +++ b/arch/powerpc/kernel/cpu_setup_power4.S | |||
@@ -130,7 +130,7 @@ _GLOBAL(__save_cpu_setup) | |||
130 | mfcr r7 | 130 | mfcr r7 |
131 | 131 | ||
132 | /* Get storage ptr */ | 132 | /* Get storage ptr */ |
133 | LOADADDR(r5,cpu_state_storage) | 133 | LOAD_REG_IMMEDIATE(r5,cpu_state_storage) |
134 | 134 | ||
135 | /* We only deal with 970 for now */ | 135 | /* We only deal with 970 for now */ |
136 | mfspr r0,SPRN_PVR | 136 | mfspr r0,SPRN_PVR |
@@ -164,7 +164,7 @@ _GLOBAL(__restore_cpu_setup) | |||
164 | /* Get storage ptr (FIXME when using anton reloc as we | 164 | /* Get storage ptr (FIXME when using anton reloc as we |
165 | * are running with translation disabled here | 165 | * are running with translation disabled here |
166 | */ | 166 | */ |
167 | LOADADDR(r5,cpu_state_storage) | 167 | LOAD_REG_IMMEDIATE(r5,cpu_state_storage) |
168 | 168 | ||
169 | /* We only deal with 970 for now */ | 169 | /* We only deal with 970 for now */ |
170 | mfspr r0,SPRN_PVR | 170 | mfspr r0,SPRN_PVR |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 43c74a6b07b1..10696456a4c6 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -55,7 +55,8 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); | |||
55 | #define COMMON_USER_POWER4 (COMMON_USER_PPC64 | PPC_FEATURE_POWER4) | 55 | #define COMMON_USER_POWER4 (COMMON_USER_PPC64 | PPC_FEATURE_POWER4) |
56 | #define COMMON_USER_POWER5 (COMMON_USER_PPC64 | PPC_FEATURE_POWER5) | 56 | #define COMMON_USER_POWER5 (COMMON_USER_PPC64 | PPC_FEATURE_POWER5) |
57 | #define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS) | 57 | #define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS) |
58 | 58 | #define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \ | |
59 | PPC_FEATURE_BOOKE) | ||
59 | 60 | ||
60 | /* We only set the spe features if the kernel was compiled with | 61 | /* We only set the spe features if the kernel was compiled with |
61 | * spe support | 62 | * spe support |
@@ -79,7 +80,8 @@ struct cpu_spec cpu_specs[] = { | |||
79 | .num_pmcs = 8, | 80 | .num_pmcs = 8, |
80 | .cpu_setup = __setup_cpu_power3, | 81 | .cpu_setup = __setup_cpu_power3, |
81 | .oprofile_cpu_type = "ppc64/power3", | 82 | .oprofile_cpu_type = "ppc64/power3", |
82 | .oprofile_type = RS64, | 83 | .oprofile_type = PPC_OPROFILE_RS64, |
84 | .platform = "power3", | ||
83 | }, | 85 | }, |
84 | { /* Power3+ */ | 86 | { /* Power3+ */ |
85 | .pvr_mask = 0xffff0000, | 87 | .pvr_mask = 0xffff0000, |
@@ -92,7 +94,8 @@ struct cpu_spec cpu_specs[] = { | |||
92 | .num_pmcs = 8, | 94 | .num_pmcs = 8, |
93 | .cpu_setup = __setup_cpu_power3, | 95 | .cpu_setup = __setup_cpu_power3, |
94 | .oprofile_cpu_type = "ppc64/power3", | 96 | .oprofile_cpu_type = "ppc64/power3", |
95 | .oprofile_type = RS64, | 97 | .oprofile_type = PPC_OPROFILE_RS64, |
98 | .platform = "power3", | ||
96 | }, | 99 | }, |
97 | { /* Northstar */ | 100 | { /* Northstar */ |
98 | .pvr_mask = 0xffff0000, | 101 | .pvr_mask = 0xffff0000, |
@@ -105,7 +108,8 @@ struct cpu_spec cpu_specs[] = { | |||
105 | .num_pmcs = 8, | 108 | .num_pmcs = 8, |
106 | .cpu_setup = __setup_cpu_power3, | 109 | .cpu_setup = __setup_cpu_power3, |
107 | .oprofile_cpu_type = "ppc64/rs64", | 110 | .oprofile_cpu_type = "ppc64/rs64", |
108 | .oprofile_type = RS64, | 111 | .oprofile_type = PPC_OPROFILE_RS64, |
112 | .platform = "rs64", | ||
109 | }, | 113 | }, |
110 | { /* Pulsar */ | 114 | { /* Pulsar */ |
111 | .pvr_mask = 0xffff0000, | 115 | .pvr_mask = 0xffff0000, |
@@ -118,7 +122,8 @@ struct cpu_spec cpu_specs[] = { | |||
118 | .num_pmcs = 8, | 122 | .num_pmcs = 8, |
119 | .cpu_setup = __setup_cpu_power3, | 123 | .cpu_setup = __setup_cpu_power3, |
120 | .oprofile_cpu_type = "ppc64/rs64", | 124 | .oprofile_cpu_type = "ppc64/rs64", |
121 | .oprofile_type = RS64, | 125 | .oprofile_type = PPC_OPROFILE_RS64, |
126 | .platform = "rs64", | ||
122 | }, | 127 | }, |
123 | { /* I-star */ | 128 | { /* I-star */ |
124 | .pvr_mask = 0xffff0000, | 129 | .pvr_mask = 0xffff0000, |
@@ -131,7 +136,8 @@ struct cpu_spec cpu_specs[] = { | |||
131 | .num_pmcs = 8, | 136 | .num_pmcs = 8, |
132 | .cpu_setup = __setup_cpu_power3, | 137 | .cpu_setup = __setup_cpu_power3, |
133 | .oprofile_cpu_type = "ppc64/rs64", | 138 | .oprofile_cpu_type = "ppc64/rs64", |
134 | .oprofile_type = RS64, | 139 | .oprofile_type = PPC_OPROFILE_RS64, |
140 | .platform = "rs64", | ||
135 | }, | 141 | }, |
136 | { /* S-star */ | 142 | { /* S-star */ |
137 | .pvr_mask = 0xffff0000, | 143 | .pvr_mask = 0xffff0000, |
@@ -144,7 +150,8 @@ struct cpu_spec cpu_specs[] = { | |||
144 | .num_pmcs = 8, | 150 | .num_pmcs = 8, |
145 | .cpu_setup = __setup_cpu_power3, | 151 | .cpu_setup = __setup_cpu_power3, |
146 | .oprofile_cpu_type = "ppc64/rs64", | 152 | .oprofile_cpu_type = "ppc64/rs64", |
147 | .oprofile_type = RS64, | 153 | .oprofile_type = PPC_OPROFILE_RS64, |
154 | .platform = "rs64", | ||
148 | }, | 155 | }, |
149 | { /* Power4 */ | 156 | { /* Power4 */ |
150 | .pvr_mask = 0xffff0000, | 157 | .pvr_mask = 0xffff0000, |
@@ -157,7 +164,8 @@ struct cpu_spec cpu_specs[] = { | |||
157 | .num_pmcs = 8, | 164 | .num_pmcs = 8, |
158 | .cpu_setup = __setup_cpu_power4, | 165 | .cpu_setup = __setup_cpu_power4, |
159 | .oprofile_cpu_type = "ppc64/power4", | 166 | .oprofile_cpu_type = "ppc64/power4", |
160 | .oprofile_type = POWER4, | 167 | .oprofile_type = PPC_OPROFILE_POWER4, |
168 | .platform = "power4", | ||
161 | }, | 169 | }, |
162 | { /* Power4+ */ | 170 | { /* Power4+ */ |
163 | .pvr_mask = 0xffff0000, | 171 | .pvr_mask = 0xffff0000, |
@@ -170,7 +178,8 @@ struct cpu_spec cpu_specs[] = { | |||
170 | .num_pmcs = 8, | 178 | .num_pmcs = 8, |
171 | .cpu_setup = __setup_cpu_power4, | 179 | .cpu_setup = __setup_cpu_power4, |
172 | .oprofile_cpu_type = "ppc64/power4", | 180 | .oprofile_cpu_type = "ppc64/power4", |
173 | .oprofile_type = POWER4, | 181 | .oprofile_type = PPC_OPROFILE_POWER4, |
182 | .platform = "power4", | ||
174 | }, | 183 | }, |
175 | { /* PPC970 */ | 184 | { /* PPC970 */ |
176 | .pvr_mask = 0xffff0000, | 185 | .pvr_mask = 0xffff0000, |
@@ -184,7 +193,8 @@ struct cpu_spec cpu_specs[] = { | |||
184 | .num_pmcs = 8, | 193 | .num_pmcs = 8, |
185 | .cpu_setup = __setup_cpu_ppc970, | 194 | .cpu_setup = __setup_cpu_ppc970, |
186 | .oprofile_cpu_type = "ppc64/970", | 195 | .oprofile_cpu_type = "ppc64/970", |
187 | .oprofile_type = POWER4, | 196 | .oprofile_type = PPC_OPROFILE_POWER4, |
197 | .platform = "ppc970", | ||
188 | }, | 198 | }, |
189 | #endif /* CONFIG_PPC64 */ | 199 | #endif /* CONFIG_PPC64 */ |
190 | #if defined(CONFIG_PPC64) || defined(CONFIG_POWER4) | 200 | #if defined(CONFIG_PPC64) || defined(CONFIG_POWER4) |
@@ -204,7 +214,8 @@ struct cpu_spec cpu_specs[] = { | |||
204 | .num_pmcs = 8, | 214 | .num_pmcs = 8, |
205 | .cpu_setup = __setup_cpu_ppc970, | 215 | .cpu_setup = __setup_cpu_ppc970, |
206 | .oprofile_cpu_type = "ppc64/970", | 216 | .oprofile_cpu_type = "ppc64/970", |
207 | .oprofile_type = POWER4, | 217 | .oprofile_type = PPC_OPROFILE_POWER4, |
218 | .platform = "ppc970", | ||
208 | }, | 219 | }, |
209 | #endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */ | 220 | #endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */ |
210 | #ifdef CONFIG_PPC64 | 221 | #ifdef CONFIG_PPC64 |
@@ -219,7 +230,8 @@ struct cpu_spec cpu_specs[] = { | |||
219 | .dcache_bsize = 128, | 230 | .dcache_bsize = 128, |
220 | .cpu_setup = __setup_cpu_ppc970, | 231 | .cpu_setup = __setup_cpu_ppc970, |
221 | .oprofile_cpu_type = "ppc64/970", | 232 | .oprofile_cpu_type = "ppc64/970", |
222 | .oprofile_type = POWER4, | 233 | .oprofile_type = PPC_OPROFILE_POWER4, |
234 | .platform = "ppc970", | ||
223 | }, | 235 | }, |
224 | { /* Power5 GR */ | 236 | { /* Power5 GR */ |
225 | .pvr_mask = 0xffff0000, | 237 | .pvr_mask = 0xffff0000, |
@@ -232,7 +244,8 @@ struct cpu_spec cpu_specs[] = { | |||
232 | .num_pmcs = 6, | 244 | .num_pmcs = 6, |
233 | .cpu_setup = __setup_cpu_power4, | 245 | .cpu_setup = __setup_cpu_power4, |
234 | .oprofile_cpu_type = "ppc64/power5", | 246 | .oprofile_cpu_type = "ppc64/power5", |
235 | .oprofile_type = POWER4, | 247 | .oprofile_type = PPC_OPROFILE_POWER4, |
248 | .platform = "power5", | ||
236 | }, | 249 | }, |
237 | { /* Power5 GS */ | 250 | { /* Power5 GS */ |
238 | .pvr_mask = 0xffff0000, | 251 | .pvr_mask = 0xffff0000, |
@@ -245,7 +258,8 @@ struct cpu_spec cpu_specs[] = { | |||
245 | .num_pmcs = 6, | 258 | .num_pmcs = 6, |
246 | .cpu_setup = __setup_cpu_power4, | 259 | .cpu_setup = __setup_cpu_power4, |
247 | .oprofile_cpu_type = "ppc64/power5+", | 260 | .oprofile_cpu_type = "ppc64/power5+", |
248 | .oprofile_type = POWER4, | 261 | .oprofile_type = PPC_OPROFILE_POWER4, |
262 | .platform = "power5+", | ||
249 | }, | 263 | }, |
250 | { /* Cell Broadband Engine */ | 264 | { /* Cell Broadband Engine */ |
251 | .pvr_mask = 0xffff0000, | 265 | .pvr_mask = 0xffff0000, |
@@ -257,6 +271,7 @@ struct cpu_spec cpu_specs[] = { | |||
257 | .icache_bsize = 128, | 271 | .icache_bsize = 128, |
258 | .dcache_bsize = 128, | 272 | .dcache_bsize = 128, |
259 | .cpu_setup = __setup_cpu_be, | 273 | .cpu_setup = __setup_cpu_be, |
274 | .platform = "ppc-cell-be", | ||
260 | }, | 275 | }, |
261 | { /* default match */ | 276 | { /* default match */ |
262 | .pvr_mask = 0x00000000, | 277 | .pvr_mask = 0x00000000, |
@@ -268,6 +283,7 @@ struct cpu_spec cpu_specs[] = { | |||
268 | .dcache_bsize = 128, | 283 | .dcache_bsize = 128, |
269 | .num_pmcs = 6, | 284 | .num_pmcs = 6, |
270 | .cpu_setup = __setup_cpu_power4, | 285 | .cpu_setup = __setup_cpu_power4, |
286 | .platform = "power4", | ||
271 | } | 287 | } |
272 | #endif /* CONFIG_PPC64 */ | 288 | #endif /* CONFIG_PPC64 */ |
273 | #ifdef CONFIG_PPC32 | 289 | #ifdef CONFIG_PPC32 |
@@ -281,6 +297,7 @@ struct cpu_spec cpu_specs[] = { | |||
281 | PPC_FEATURE_UNIFIED_CACHE | PPC_FEATURE_NO_TB, | 297 | PPC_FEATURE_UNIFIED_CACHE | PPC_FEATURE_NO_TB, |
282 | .icache_bsize = 32, | 298 | .icache_bsize = 32, |
283 | .dcache_bsize = 32, | 299 | .dcache_bsize = 32, |
300 | .platform = "ppc601", | ||
284 | }, | 301 | }, |
285 | { /* 603 */ | 302 | { /* 603 */ |
286 | .pvr_mask = 0xffff0000, | 303 | .pvr_mask = 0xffff0000, |
@@ -290,7 +307,8 @@ struct cpu_spec cpu_specs[] = { | |||
290 | .cpu_user_features = COMMON_USER, | 307 | .cpu_user_features = COMMON_USER, |
291 | .icache_bsize = 32, | 308 | .icache_bsize = 32, |
292 | .dcache_bsize = 32, | 309 | .dcache_bsize = 32, |
293 | .cpu_setup = __setup_cpu_603 | 310 | .cpu_setup = __setup_cpu_603, |
311 | .platform = "ppc603", | ||
294 | }, | 312 | }, |
295 | { /* 603e */ | 313 | { /* 603e */ |
296 | .pvr_mask = 0xffff0000, | 314 | .pvr_mask = 0xffff0000, |
@@ -300,7 +318,8 @@ struct cpu_spec cpu_specs[] = { | |||
300 | .cpu_user_features = COMMON_USER, | 318 | .cpu_user_features = COMMON_USER, |
301 | .icache_bsize = 32, | 319 | .icache_bsize = 32, |
302 | .dcache_bsize = 32, | 320 | .dcache_bsize = 32, |
303 | .cpu_setup = __setup_cpu_603 | 321 | .cpu_setup = __setup_cpu_603, |
322 | .platform = "ppc603", | ||
304 | }, | 323 | }, |
305 | { /* 603ev */ | 324 | { /* 603ev */ |
306 | .pvr_mask = 0xffff0000, | 325 | .pvr_mask = 0xffff0000, |
@@ -310,7 +329,8 @@ struct cpu_spec cpu_specs[] = { | |||
310 | .cpu_user_features = COMMON_USER, | 329 | .cpu_user_features = COMMON_USER, |
311 | .icache_bsize = 32, | 330 | .icache_bsize = 32, |
312 | .dcache_bsize = 32, | 331 | .dcache_bsize = 32, |
313 | .cpu_setup = __setup_cpu_603 | 332 | .cpu_setup = __setup_cpu_603, |
333 | .platform = "ppc603", | ||
314 | }, | 334 | }, |
315 | { /* 604 */ | 335 | { /* 604 */ |
316 | .pvr_mask = 0xffff0000, | 336 | .pvr_mask = 0xffff0000, |
@@ -321,7 +341,8 @@ struct cpu_spec cpu_specs[] = { | |||
321 | .icache_bsize = 32, | 341 | .icache_bsize = 32, |
322 | .dcache_bsize = 32, | 342 | .dcache_bsize = 32, |
323 | .num_pmcs = 2, | 343 | .num_pmcs = 2, |
324 | .cpu_setup = __setup_cpu_604 | 344 | .cpu_setup = __setup_cpu_604, |
345 | .platform = "ppc604", | ||
325 | }, | 346 | }, |
326 | { /* 604e */ | 347 | { /* 604e */ |
327 | .pvr_mask = 0xfffff000, | 348 | .pvr_mask = 0xfffff000, |
@@ -332,7 +353,8 @@ struct cpu_spec cpu_specs[] = { | |||
332 | .icache_bsize = 32, | 353 | .icache_bsize = 32, |
333 | .dcache_bsize = 32, | 354 | .dcache_bsize = 32, |
334 | .num_pmcs = 4, | 355 | .num_pmcs = 4, |
335 | .cpu_setup = __setup_cpu_604 | 356 | .cpu_setup = __setup_cpu_604, |
357 | .platform = "ppc604", | ||
336 | }, | 358 | }, |
337 | { /* 604r */ | 359 | { /* 604r */ |
338 | .pvr_mask = 0xffff0000, | 360 | .pvr_mask = 0xffff0000, |
@@ -343,7 +365,8 @@ struct cpu_spec cpu_specs[] = { | |||
343 | .icache_bsize = 32, | 365 | .icache_bsize = 32, |
344 | .dcache_bsize = 32, | 366 | .dcache_bsize = 32, |
345 | .num_pmcs = 4, | 367 | .num_pmcs = 4, |
346 | .cpu_setup = __setup_cpu_604 | 368 | .cpu_setup = __setup_cpu_604, |
369 | .platform = "ppc604", | ||
347 | }, | 370 | }, |
348 | { /* 604ev */ | 371 | { /* 604ev */ |
349 | .pvr_mask = 0xffff0000, | 372 | .pvr_mask = 0xffff0000, |
@@ -354,7 +377,8 @@ struct cpu_spec cpu_specs[] = { | |||
354 | .icache_bsize = 32, | 377 | .icache_bsize = 32, |
355 | .dcache_bsize = 32, | 378 | .dcache_bsize = 32, |
356 | .num_pmcs = 4, | 379 | .num_pmcs = 4, |
357 | .cpu_setup = __setup_cpu_604 | 380 | .cpu_setup = __setup_cpu_604, |
381 | .platform = "ppc604", | ||
358 | }, | 382 | }, |
359 | { /* 740/750 (0x4202, don't support TAU ?) */ | 383 | { /* 740/750 (0x4202, don't support TAU ?) */ |
360 | .pvr_mask = 0xffffffff, | 384 | .pvr_mask = 0xffffffff, |
@@ -365,7 +389,8 @@ struct cpu_spec cpu_specs[] = { | |||
365 | .icache_bsize = 32, | 389 | .icache_bsize = 32, |
366 | .dcache_bsize = 32, | 390 | .dcache_bsize = 32, |
367 | .num_pmcs = 4, | 391 | .num_pmcs = 4, |
368 | .cpu_setup = __setup_cpu_750 | 392 | .cpu_setup = __setup_cpu_750, |
393 | .platform = "ppc750", | ||
369 | }, | 394 | }, |
370 | { /* 750CX (80100 and 8010x?) */ | 395 | { /* 750CX (80100 and 8010x?) */ |
371 | .pvr_mask = 0xfffffff0, | 396 | .pvr_mask = 0xfffffff0, |
@@ -376,7 +401,8 @@ struct cpu_spec cpu_specs[] = { | |||
376 | .icache_bsize = 32, | 401 | .icache_bsize = 32, |
377 | .dcache_bsize = 32, | 402 | .dcache_bsize = 32, |
378 | .num_pmcs = 4, | 403 | .num_pmcs = 4, |
379 | .cpu_setup = __setup_cpu_750cx | 404 | .cpu_setup = __setup_cpu_750cx, |
405 | .platform = "ppc750", | ||
380 | }, | 406 | }, |
381 | { /* 750CX (82201 and 82202) */ | 407 | { /* 750CX (82201 and 82202) */ |
382 | .pvr_mask = 0xfffffff0, | 408 | .pvr_mask = 0xfffffff0, |
@@ -387,7 +413,8 @@ struct cpu_spec cpu_specs[] = { | |||
387 | .icache_bsize = 32, | 413 | .icache_bsize = 32, |
388 | .dcache_bsize = 32, | 414 | .dcache_bsize = 32, |
389 | .num_pmcs = 4, | 415 | .num_pmcs = 4, |
390 | .cpu_setup = __setup_cpu_750cx | 416 | .cpu_setup = __setup_cpu_750cx, |
417 | .platform = "ppc750", | ||
391 | }, | 418 | }, |
392 | { /* 750CXe (82214) */ | 419 | { /* 750CXe (82214) */ |
393 | .pvr_mask = 0xfffffff0, | 420 | .pvr_mask = 0xfffffff0, |
@@ -398,7 +425,8 @@ struct cpu_spec cpu_specs[] = { | |||
398 | .icache_bsize = 32, | 425 | .icache_bsize = 32, |
399 | .dcache_bsize = 32, | 426 | .dcache_bsize = 32, |
400 | .num_pmcs = 4, | 427 | .num_pmcs = 4, |
401 | .cpu_setup = __setup_cpu_750cx | 428 | .cpu_setup = __setup_cpu_750cx, |
429 | .platform = "ppc750", | ||
402 | }, | 430 | }, |
403 | { /* 750CXe "Gekko" (83214) */ | 431 | { /* 750CXe "Gekko" (83214) */ |
404 | .pvr_mask = 0xffffffff, | 432 | .pvr_mask = 0xffffffff, |
@@ -409,7 +437,8 @@ struct cpu_spec cpu_specs[] = { | |||
409 | .icache_bsize = 32, | 437 | .icache_bsize = 32, |
410 | .dcache_bsize = 32, | 438 | .dcache_bsize = 32, |
411 | .num_pmcs = 4, | 439 | .num_pmcs = 4, |
412 | .cpu_setup = __setup_cpu_750cx | 440 | .cpu_setup = __setup_cpu_750cx, |
441 | .platform = "ppc750", | ||
413 | }, | 442 | }, |
414 | { /* 745/755 */ | 443 | { /* 745/755 */ |
415 | .pvr_mask = 0xfffff000, | 444 | .pvr_mask = 0xfffff000, |
@@ -420,7 +449,8 @@ struct cpu_spec cpu_specs[] = { | |||
420 | .icache_bsize = 32, | 449 | .icache_bsize = 32, |
421 | .dcache_bsize = 32, | 450 | .dcache_bsize = 32, |
422 | .num_pmcs = 4, | 451 | .num_pmcs = 4, |
423 | .cpu_setup = __setup_cpu_750 | 452 | .cpu_setup = __setup_cpu_750, |
453 | .platform = "ppc750", | ||
424 | }, | 454 | }, |
425 | { /* 750FX rev 1.x */ | 455 | { /* 750FX rev 1.x */ |
426 | .pvr_mask = 0xffffff00, | 456 | .pvr_mask = 0xffffff00, |
@@ -431,7 +461,8 @@ struct cpu_spec cpu_specs[] = { | |||
431 | .icache_bsize = 32, | 461 | .icache_bsize = 32, |
432 | .dcache_bsize = 32, | 462 | .dcache_bsize = 32, |
433 | .num_pmcs = 4, | 463 | .num_pmcs = 4, |
434 | .cpu_setup = __setup_cpu_750 | 464 | .cpu_setup = __setup_cpu_750, |
465 | .platform = "ppc750", | ||
435 | }, | 466 | }, |
436 | { /* 750FX rev 2.0 must disable HID0[DPM] */ | 467 | { /* 750FX rev 2.0 must disable HID0[DPM] */ |
437 | .pvr_mask = 0xffffffff, | 468 | .pvr_mask = 0xffffffff, |
@@ -442,7 +473,8 @@ struct cpu_spec cpu_specs[] = { | |||
442 | .icache_bsize = 32, | 473 | .icache_bsize = 32, |
443 | .dcache_bsize = 32, | 474 | .dcache_bsize = 32, |
444 | .num_pmcs = 4, | 475 | .num_pmcs = 4, |
445 | .cpu_setup = __setup_cpu_750 | 476 | .cpu_setup = __setup_cpu_750, |
477 | .platform = "ppc750", | ||
446 | }, | 478 | }, |
447 | { /* 750FX (All revs except 2.0) */ | 479 | { /* 750FX (All revs except 2.0) */ |
448 | .pvr_mask = 0xffff0000, | 480 | .pvr_mask = 0xffff0000, |
@@ -453,7 +485,8 @@ struct cpu_spec cpu_specs[] = { | |||
453 | .icache_bsize = 32, | 485 | .icache_bsize = 32, |
454 | .dcache_bsize = 32, | 486 | .dcache_bsize = 32, |
455 | .num_pmcs = 4, | 487 | .num_pmcs = 4, |
456 | .cpu_setup = __setup_cpu_750fx | 488 | .cpu_setup = __setup_cpu_750fx, |
489 | .platform = "ppc750", | ||
457 | }, | 490 | }, |
458 | { /* 750GX */ | 491 | { /* 750GX */ |
459 | .pvr_mask = 0xffff0000, | 492 | .pvr_mask = 0xffff0000, |
@@ -464,7 +497,8 @@ struct cpu_spec cpu_specs[] = { | |||
464 | .icache_bsize = 32, | 497 | .icache_bsize = 32, |
465 | .dcache_bsize = 32, | 498 | .dcache_bsize = 32, |
466 | .num_pmcs = 4, | 499 | .num_pmcs = 4, |
467 | .cpu_setup = __setup_cpu_750fx | 500 | .cpu_setup = __setup_cpu_750fx, |
501 | .platform = "ppc750", | ||
468 | }, | 502 | }, |
469 | { /* 740/750 (L2CR bit need fixup for 740) */ | 503 | { /* 740/750 (L2CR bit need fixup for 740) */ |
470 | .pvr_mask = 0xffff0000, | 504 | .pvr_mask = 0xffff0000, |
@@ -475,7 +509,8 @@ struct cpu_spec cpu_specs[] = { | |||
475 | .icache_bsize = 32, | 509 | .icache_bsize = 32, |
476 | .dcache_bsize = 32, | 510 | .dcache_bsize = 32, |
477 | .num_pmcs = 4, | 511 | .num_pmcs = 4, |
478 | .cpu_setup = __setup_cpu_750 | 512 | .cpu_setup = __setup_cpu_750, |
513 | .platform = "ppc750", | ||
479 | }, | 514 | }, |
480 | { /* 7400 rev 1.1 ? (no TAU) */ | 515 | { /* 7400 rev 1.1 ? (no TAU) */ |
481 | .pvr_mask = 0xffffffff, | 516 | .pvr_mask = 0xffffffff, |
@@ -486,7 +521,8 @@ struct cpu_spec cpu_specs[] = { | |||
486 | .icache_bsize = 32, | 521 | .icache_bsize = 32, |
487 | .dcache_bsize = 32, | 522 | .dcache_bsize = 32, |
488 | .num_pmcs = 4, | 523 | .num_pmcs = 4, |
489 | .cpu_setup = __setup_cpu_7400 | 524 | .cpu_setup = __setup_cpu_7400, |
525 | .platform = "ppc7400", | ||
490 | }, | 526 | }, |
491 | { /* 7400 */ | 527 | { /* 7400 */ |
492 | .pvr_mask = 0xffff0000, | 528 | .pvr_mask = 0xffff0000, |
@@ -497,7 +533,8 @@ struct cpu_spec cpu_specs[] = { | |||
497 | .icache_bsize = 32, | 533 | .icache_bsize = 32, |
498 | .dcache_bsize = 32, | 534 | .dcache_bsize = 32, |
499 | .num_pmcs = 4, | 535 | .num_pmcs = 4, |
500 | .cpu_setup = __setup_cpu_7400 | 536 | .cpu_setup = __setup_cpu_7400, |
537 | .platform = "ppc7400", | ||
501 | }, | 538 | }, |
502 | { /* 7410 */ | 539 | { /* 7410 */ |
503 | .pvr_mask = 0xffff0000, | 540 | .pvr_mask = 0xffff0000, |
@@ -508,7 +545,8 @@ struct cpu_spec cpu_specs[] = { | |||
508 | .icache_bsize = 32, | 545 | .icache_bsize = 32, |
509 | .dcache_bsize = 32, | 546 | .dcache_bsize = 32, |
510 | .num_pmcs = 4, | 547 | .num_pmcs = 4, |
511 | .cpu_setup = __setup_cpu_7410 | 548 | .cpu_setup = __setup_cpu_7410, |
549 | .platform = "ppc7400", | ||
512 | }, | 550 | }, |
513 | { /* 7450 2.0 - no doze/nap */ | 551 | { /* 7450 2.0 - no doze/nap */ |
514 | .pvr_mask = 0xffffffff, | 552 | .pvr_mask = 0xffffffff, |
@@ -521,7 +559,8 @@ struct cpu_spec cpu_specs[] = { | |||
521 | .num_pmcs = 6, | 559 | .num_pmcs = 6, |
522 | .cpu_setup = __setup_cpu_745x, | 560 | .cpu_setup = __setup_cpu_745x, |
523 | .oprofile_cpu_type = "ppc/7450", | 561 | .oprofile_cpu_type = "ppc/7450", |
524 | .oprofile_type = G4, | 562 | .oprofile_type = PPC_OPROFILE_G4, |
563 | .platform = "ppc7450", | ||
525 | }, | 564 | }, |
526 | { /* 7450 2.1 */ | 565 | { /* 7450 2.1 */ |
527 | .pvr_mask = 0xffffffff, | 566 | .pvr_mask = 0xffffffff, |
@@ -534,7 +573,8 @@ struct cpu_spec cpu_specs[] = { | |||
534 | .num_pmcs = 6, | 573 | .num_pmcs = 6, |
535 | .cpu_setup = __setup_cpu_745x, | 574 | .cpu_setup = __setup_cpu_745x, |
536 | .oprofile_cpu_type = "ppc/7450", | 575 | .oprofile_cpu_type = "ppc/7450", |
537 | .oprofile_type = G4, | 576 | .oprofile_type = PPC_OPROFILE_G4, |
577 | .platform = "ppc7450", | ||
538 | }, | 578 | }, |
539 | { /* 7450 2.3 and newer */ | 579 | { /* 7450 2.3 and newer */ |
540 | .pvr_mask = 0xffff0000, | 580 | .pvr_mask = 0xffff0000, |
@@ -547,7 +587,8 @@ struct cpu_spec cpu_specs[] = { | |||
547 | .num_pmcs = 6, | 587 | .num_pmcs = 6, |
548 | .cpu_setup = __setup_cpu_745x, | 588 | .cpu_setup = __setup_cpu_745x, |
549 | .oprofile_cpu_type = "ppc/7450", | 589 | .oprofile_cpu_type = "ppc/7450", |
550 | .oprofile_type = G4, | 590 | .oprofile_type = PPC_OPROFILE_G4, |
591 | .platform = "ppc7450", | ||
551 | }, | 592 | }, |
552 | { /* 7455 rev 1.x */ | 593 | { /* 7455 rev 1.x */ |
553 | .pvr_mask = 0xffffff00, | 594 | .pvr_mask = 0xffffff00, |
@@ -560,7 +601,8 @@ struct cpu_spec cpu_specs[] = { | |||
560 | .num_pmcs = 6, | 601 | .num_pmcs = 6, |
561 | .cpu_setup = __setup_cpu_745x, | 602 | .cpu_setup = __setup_cpu_745x, |
562 | .oprofile_cpu_type = "ppc/7450", | 603 | .oprofile_cpu_type = "ppc/7450", |
563 | .oprofile_type = G4, | 604 | .oprofile_type = PPC_OPROFILE_G4, |
605 | .platform = "ppc7450", | ||
564 | }, | 606 | }, |
565 | { /* 7455 rev 2.0 */ | 607 | { /* 7455 rev 2.0 */ |
566 | .pvr_mask = 0xffffffff, | 608 | .pvr_mask = 0xffffffff, |
@@ -573,7 +615,8 @@ struct cpu_spec cpu_specs[] = { | |||
573 | .num_pmcs = 6, | 615 | .num_pmcs = 6, |
574 | .cpu_setup = __setup_cpu_745x, | 616 | .cpu_setup = __setup_cpu_745x, |
575 | .oprofile_cpu_type = "ppc/7450", | 617 | .oprofile_cpu_type = "ppc/7450", |
576 | .oprofile_type = G4, | 618 | .oprofile_type = PPC_OPROFILE_G4, |
619 | .platform = "ppc7450", | ||
577 | }, | 620 | }, |
578 | { /* 7455 others */ | 621 | { /* 7455 others */ |
579 | .pvr_mask = 0xffff0000, | 622 | .pvr_mask = 0xffff0000, |
@@ -586,7 +629,8 @@ struct cpu_spec cpu_specs[] = { | |||
586 | .num_pmcs = 6, | 629 | .num_pmcs = 6, |
587 | .cpu_setup = __setup_cpu_745x, | 630 | .cpu_setup = __setup_cpu_745x, |
588 | .oprofile_cpu_type = "ppc/7450", | 631 | .oprofile_cpu_type = "ppc/7450", |
589 | .oprofile_type = G4, | 632 | .oprofile_type = PPC_OPROFILE_G4, |
633 | .platform = "ppc7450", | ||
590 | }, | 634 | }, |
591 | { /* 7447/7457 Rev 1.0 */ | 635 | { /* 7447/7457 Rev 1.0 */ |
592 | .pvr_mask = 0xffffffff, | 636 | .pvr_mask = 0xffffffff, |
@@ -599,7 +643,8 @@ struct cpu_spec cpu_specs[] = { | |||
599 | .num_pmcs = 6, | 643 | .num_pmcs = 6, |
600 | .cpu_setup = __setup_cpu_745x, | 644 | .cpu_setup = __setup_cpu_745x, |
601 | .oprofile_cpu_type = "ppc/7450", | 645 | .oprofile_cpu_type = "ppc/7450", |
602 | .oprofile_type = G4, | 646 | .oprofile_type = PPC_OPROFILE_G4, |
647 | .platform = "ppc7450", | ||
603 | }, | 648 | }, |
604 | { /* 7447/7457 Rev 1.1 */ | 649 | { /* 7447/7457 Rev 1.1 */ |
605 | .pvr_mask = 0xffffffff, | 650 | .pvr_mask = 0xffffffff, |
@@ -612,7 +657,8 @@ struct cpu_spec cpu_specs[] = { | |||
612 | .num_pmcs = 6, | 657 | .num_pmcs = 6, |
613 | .cpu_setup = __setup_cpu_745x, | 658 | .cpu_setup = __setup_cpu_745x, |
614 | .oprofile_cpu_type = "ppc/7450", | 659 | .oprofile_cpu_type = "ppc/7450", |
615 | .oprofile_type = G4, | 660 | .oprofile_type = PPC_OPROFILE_G4, |
661 | .platform = "ppc7450", | ||
616 | }, | 662 | }, |
617 | { /* 7447/7457 Rev 1.2 and later */ | 663 | { /* 7447/7457 Rev 1.2 and later */ |
618 | .pvr_mask = 0xffff0000, | 664 | .pvr_mask = 0xffff0000, |
@@ -625,7 +671,8 @@ struct cpu_spec cpu_specs[] = { | |||
625 | .num_pmcs = 6, | 671 | .num_pmcs = 6, |
626 | .cpu_setup = __setup_cpu_745x, | 672 | .cpu_setup = __setup_cpu_745x, |
627 | .oprofile_cpu_type = "ppc/7450", | 673 | .oprofile_cpu_type = "ppc/7450", |
628 | .oprofile_type = G4, | 674 | .oprofile_type = PPC_OPROFILE_G4, |
675 | .platform = "ppc7450", | ||
629 | }, | 676 | }, |
630 | { /* 7447A */ | 677 | { /* 7447A */ |
631 | .pvr_mask = 0xffff0000, | 678 | .pvr_mask = 0xffff0000, |
@@ -638,7 +685,8 @@ struct cpu_spec cpu_specs[] = { | |||
638 | .num_pmcs = 6, | 685 | .num_pmcs = 6, |
639 | .cpu_setup = __setup_cpu_745x, | 686 | .cpu_setup = __setup_cpu_745x, |
640 | .oprofile_cpu_type = "ppc/7450", | 687 | .oprofile_cpu_type = "ppc/7450", |
641 | .oprofile_type = G4, | 688 | .oprofile_type = PPC_OPROFILE_G4, |
689 | .platform = "ppc7450", | ||
642 | }, | 690 | }, |
643 | { /* 7448 */ | 691 | { /* 7448 */ |
644 | .pvr_mask = 0xffff0000, | 692 | .pvr_mask = 0xffff0000, |
@@ -651,7 +699,8 @@ struct cpu_spec cpu_specs[] = { | |||
651 | .num_pmcs = 6, | 699 | .num_pmcs = 6, |
652 | .cpu_setup = __setup_cpu_745x, | 700 | .cpu_setup = __setup_cpu_745x, |
653 | .oprofile_cpu_type = "ppc/7450", | 701 | .oprofile_cpu_type = "ppc/7450", |
654 | .oprofile_type = G4, | 702 | .oprofile_type = PPC_OPROFILE_G4, |
703 | .platform = "ppc7450", | ||
655 | }, | 704 | }, |
656 | { /* 82xx (8240, 8245, 8260 are all 603e cores) */ | 705 | { /* 82xx (8240, 8245, 8260 are all 603e cores) */ |
657 | .pvr_mask = 0x7fff0000, | 706 | .pvr_mask = 0x7fff0000, |
@@ -661,7 +710,8 @@ struct cpu_spec cpu_specs[] = { | |||
661 | .cpu_user_features = COMMON_USER, | 710 | .cpu_user_features = COMMON_USER, |
662 | .icache_bsize = 32, | 711 | .icache_bsize = 32, |
663 | .dcache_bsize = 32, | 712 | .dcache_bsize = 32, |
664 | .cpu_setup = __setup_cpu_603 | 713 | .cpu_setup = __setup_cpu_603, |
714 | .platform = "ppc603", | ||
665 | }, | 715 | }, |
666 | { /* All G2_LE (603e core, plus some) have the same pvr */ | 716 | { /* All G2_LE (603e core, plus some) have the same pvr */ |
667 | .pvr_mask = 0x7fff0000, | 717 | .pvr_mask = 0x7fff0000, |
@@ -671,7 +721,8 @@ struct cpu_spec cpu_specs[] = { | |||
671 | .cpu_user_features = COMMON_USER, | 721 | .cpu_user_features = COMMON_USER, |
672 | .icache_bsize = 32, | 722 | .icache_bsize = 32, |
673 | .dcache_bsize = 32, | 723 | .dcache_bsize = 32, |
674 | .cpu_setup = __setup_cpu_603 | 724 | .cpu_setup = __setup_cpu_603, |
725 | .platform = "ppc603", | ||
675 | }, | 726 | }, |
676 | { /* e300 (a 603e core, plus some) on 83xx */ | 727 | { /* e300 (a 603e core, plus some) on 83xx */ |
677 | .pvr_mask = 0x7fff0000, | 728 | .pvr_mask = 0x7fff0000, |
@@ -681,7 +732,8 @@ struct cpu_spec cpu_specs[] = { | |||
681 | .cpu_user_features = COMMON_USER, | 732 | .cpu_user_features = COMMON_USER, |
682 | .icache_bsize = 32, | 733 | .icache_bsize = 32, |
683 | .dcache_bsize = 32, | 734 | .dcache_bsize = 32, |
684 | .cpu_setup = __setup_cpu_603 | 735 | .cpu_setup = __setup_cpu_603, |
736 | .platform = "ppc603", | ||
685 | }, | 737 | }, |
686 | { /* default match, we assume split I/D cache & TB (non-601)... */ | 738 | { /* default match, we assume split I/D cache & TB (non-601)... */ |
687 | .pvr_mask = 0x00000000, | 739 | .pvr_mask = 0x00000000, |
@@ -691,6 +743,7 @@ struct cpu_spec cpu_specs[] = { | |||
691 | .cpu_user_features = COMMON_USER, | 743 | .cpu_user_features = COMMON_USER, |
692 | .icache_bsize = 32, | 744 | .icache_bsize = 32, |
693 | .dcache_bsize = 32, | 745 | .dcache_bsize = 32, |
746 | .platform = "ppc603", | ||
694 | }, | 747 | }, |
695 | #endif /* CLASSIC_PPC */ | 748 | #endif /* CLASSIC_PPC */ |
696 | #ifdef CONFIG_8xx | 749 | #ifdef CONFIG_8xx |
@@ -704,6 +757,7 @@ struct cpu_spec cpu_specs[] = { | |||
704 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 757 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, |
705 | .icache_bsize = 16, | 758 | .icache_bsize = 16, |
706 | .dcache_bsize = 16, | 759 | .dcache_bsize = 16, |
760 | .platform = "ppc823", | ||
707 | }, | 761 | }, |
708 | #endif /* CONFIG_8xx */ | 762 | #endif /* CONFIG_8xx */ |
709 | #ifdef CONFIG_40x | 763 | #ifdef CONFIG_40x |
@@ -715,6 +769,7 @@ struct cpu_spec cpu_specs[] = { | |||
715 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 769 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, |
716 | .icache_bsize = 16, | 770 | .icache_bsize = 16, |
717 | .dcache_bsize = 16, | 771 | .dcache_bsize = 16, |
772 | .platform = "ppc403", | ||
718 | }, | 773 | }, |
719 | { /* 403GCX */ | 774 | { /* 403GCX */ |
720 | .pvr_mask = 0xffffff00, | 775 | .pvr_mask = 0xffffff00, |
@@ -725,6 +780,7 @@ struct cpu_spec cpu_specs[] = { | |||
725 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_NO_TB, | 780 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_NO_TB, |
726 | .icache_bsize = 16, | 781 | .icache_bsize = 16, |
727 | .dcache_bsize = 16, | 782 | .dcache_bsize = 16, |
783 | .platform = "ppc403", | ||
728 | }, | 784 | }, |
729 | { /* 403G ?? */ | 785 | { /* 403G ?? */ |
730 | .pvr_mask = 0xffff0000, | 786 | .pvr_mask = 0xffff0000, |
@@ -734,6 +790,7 @@ struct cpu_spec cpu_specs[] = { | |||
734 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 790 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, |
735 | .icache_bsize = 16, | 791 | .icache_bsize = 16, |
736 | .dcache_bsize = 16, | 792 | .dcache_bsize = 16, |
793 | .platform = "ppc403", | ||
737 | }, | 794 | }, |
738 | { /* 405GP */ | 795 | { /* 405GP */ |
739 | .pvr_mask = 0xffff0000, | 796 | .pvr_mask = 0xffff0000, |
@@ -744,6 +801,7 @@ struct cpu_spec cpu_specs[] = { | |||
744 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | 801 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, |
745 | .icache_bsize = 32, | 802 | .icache_bsize = 32, |
746 | .dcache_bsize = 32, | 803 | .dcache_bsize = 32, |
804 | .platform = "ppc405", | ||
747 | }, | 805 | }, |
748 | { /* STB 03xxx */ | 806 | { /* STB 03xxx */ |
749 | .pvr_mask = 0xffff0000, | 807 | .pvr_mask = 0xffff0000, |
@@ -754,6 +812,7 @@ struct cpu_spec cpu_specs[] = { | |||
754 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | 812 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, |
755 | .icache_bsize = 32, | 813 | .icache_bsize = 32, |
756 | .dcache_bsize = 32, | 814 | .dcache_bsize = 32, |
815 | .platform = "ppc405", | ||
757 | }, | 816 | }, |
758 | { /* STB 04xxx */ | 817 | { /* STB 04xxx */ |
759 | .pvr_mask = 0xffff0000, | 818 | .pvr_mask = 0xffff0000, |
@@ -764,6 +823,7 @@ struct cpu_spec cpu_specs[] = { | |||
764 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | 823 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, |
765 | .icache_bsize = 32, | 824 | .icache_bsize = 32, |
766 | .dcache_bsize = 32, | 825 | .dcache_bsize = 32, |
826 | .platform = "ppc405", | ||
767 | }, | 827 | }, |
768 | { /* NP405L */ | 828 | { /* NP405L */ |
769 | .pvr_mask = 0xffff0000, | 829 | .pvr_mask = 0xffff0000, |
@@ -774,6 +834,7 @@ struct cpu_spec cpu_specs[] = { | |||
774 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | 834 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, |
775 | .icache_bsize = 32, | 835 | .icache_bsize = 32, |
776 | .dcache_bsize = 32, | 836 | .dcache_bsize = 32, |
837 | .platform = "ppc405", | ||
777 | }, | 838 | }, |
778 | { /* NP4GS3 */ | 839 | { /* NP4GS3 */ |
779 | .pvr_mask = 0xffff0000, | 840 | .pvr_mask = 0xffff0000, |
@@ -784,6 +845,7 @@ struct cpu_spec cpu_specs[] = { | |||
784 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | 845 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, |
785 | .icache_bsize = 32, | 846 | .icache_bsize = 32, |
786 | .dcache_bsize = 32, | 847 | .dcache_bsize = 32, |
848 | .platform = "ppc405", | ||
787 | }, | 849 | }, |
788 | { /* NP405H */ | 850 | { /* NP405H */ |
789 | .pvr_mask = 0xffff0000, | 851 | .pvr_mask = 0xffff0000, |
@@ -794,6 +856,7 @@ struct cpu_spec cpu_specs[] = { | |||
794 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | 856 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, |
795 | .icache_bsize = 32, | 857 | .icache_bsize = 32, |
796 | .dcache_bsize = 32, | 858 | .dcache_bsize = 32, |
859 | .platform = "ppc405", | ||
797 | }, | 860 | }, |
798 | { /* 405GPr */ | 861 | { /* 405GPr */ |
799 | .pvr_mask = 0xffff0000, | 862 | .pvr_mask = 0xffff0000, |
@@ -804,6 +867,7 @@ struct cpu_spec cpu_specs[] = { | |||
804 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | 867 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, |
805 | .icache_bsize = 32, | 868 | .icache_bsize = 32, |
806 | .dcache_bsize = 32, | 869 | .dcache_bsize = 32, |
870 | .platform = "ppc405", | ||
807 | }, | 871 | }, |
808 | { /* STBx25xx */ | 872 | { /* STBx25xx */ |
809 | .pvr_mask = 0xffff0000, | 873 | .pvr_mask = 0xffff0000, |
@@ -814,6 +878,7 @@ struct cpu_spec cpu_specs[] = { | |||
814 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | 878 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, |
815 | .icache_bsize = 32, | 879 | .icache_bsize = 32, |
816 | .dcache_bsize = 32, | 880 | .dcache_bsize = 32, |
881 | .platform = "ppc405", | ||
817 | }, | 882 | }, |
818 | { /* 405LP */ | 883 | { /* 405LP */ |
819 | .pvr_mask = 0xffff0000, | 884 | .pvr_mask = 0xffff0000, |
@@ -823,6 +888,7 @@ struct cpu_spec cpu_specs[] = { | |||
823 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 888 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, |
824 | .icache_bsize = 32, | 889 | .icache_bsize = 32, |
825 | .dcache_bsize = 32, | 890 | .dcache_bsize = 32, |
891 | .platform = "ppc405", | ||
826 | }, | 892 | }, |
827 | { /* Xilinx Virtex-II Pro */ | 893 | { /* Xilinx Virtex-II Pro */ |
828 | .pvr_mask = 0xffff0000, | 894 | .pvr_mask = 0xffff0000, |
@@ -833,6 +899,7 @@ struct cpu_spec cpu_specs[] = { | |||
833 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | 899 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, |
834 | .icache_bsize = 32, | 900 | .icache_bsize = 32, |
835 | .dcache_bsize = 32, | 901 | .dcache_bsize = 32, |
902 | .platform = "ppc405", | ||
836 | }, | 903 | }, |
837 | { /* 405EP */ | 904 | { /* 405EP */ |
838 | .pvr_mask = 0xffff0000, | 905 | .pvr_mask = 0xffff0000, |
@@ -843,6 +910,7 @@ struct cpu_spec cpu_specs[] = { | |||
843 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | 910 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, |
844 | .icache_bsize = 32, | 911 | .icache_bsize = 32, |
845 | .dcache_bsize = 32, | 912 | .dcache_bsize = 32, |
913 | .platform = "ppc405", | ||
846 | }, | 914 | }, |
847 | 915 | ||
848 | #endif /* CONFIG_40x */ | 916 | #endif /* CONFIG_40x */ |
@@ -852,81 +920,90 @@ struct cpu_spec cpu_specs[] = { | |||
852 | .pvr_value = 0x40000850, | 920 | .pvr_value = 0x40000850, |
853 | .cpu_name = "440EP Rev. A", | 921 | .cpu_name = "440EP Rev. A", |
854 | .cpu_features = CPU_FTRS_44X, | 922 | .cpu_features = CPU_FTRS_44X, |
855 | .cpu_user_features = COMMON_USER, /* 440EP has an FPU */ | 923 | .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, |
856 | .icache_bsize = 32, | 924 | .icache_bsize = 32, |
857 | .dcache_bsize = 32, | 925 | .dcache_bsize = 32, |
926 | .platform = "ppc440", | ||
858 | }, | 927 | }, |
859 | { | 928 | { |
860 | .pvr_mask = 0xf0000fff, | 929 | .pvr_mask = 0xf0000fff, |
861 | .pvr_value = 0x400008d3, | 930 | .pvr_value = 0x400008d3, |
862 | .cpu_name = "440EP Rev. B", | 931 | .cpu_name = "440EP Rev. B", |
863 | .cpu_features = CPU_FTRS_44X, | 932 | .cpu_features = CPU_FTRS_44X, |
864 | .cpu_user_features = COMMON_USER, /* 440EP has an FPU */ | 933 | .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, |
865 | .icache_bsize = 32, | 934 | .icache_bsize = 32, |
866 | .dcache_bsize = 32, | 935 | .dcache_bsize = 32, |
936 | .platform = "ppc440", | ||
867 | }, | 937 | }, |
868 | { /* 440GP Rev. B */ | 938 | { /* 440GP Rev. B */ |
869 | .pvr_mask = 0xf0000fff, | 939 | .pvr_mask = 0xf0000fff, |
870 | .pvr_value = 0x40000440, | 940 | .pvr_value = 0x40000440, |
871 | .cpu_name = "440GP Rev. B", | 941 | .cpu_name = "440GP Rev. B", |
872 | .cpu_features = CPU_FTRS_44X, | 942 | .cpu_features = CPU_FTRS_44X, |
873 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 943 | .cpu_user_features = COMMON_USER_BOOKE, |
874 | .icache_bsize = 32, | 944 | .icache_bsize = 32, |
875 | .dcache_bsize = 32, | 945 | .dcache_bsize = 32, |
946 | .platform = "ppc440gp", | ||
876 | }, | 947 | }, |
877 | { /* 440GP Rev. C */ | 948 | { /* 440GP Rev. C */ |
878 | .pvr_mask = 0xf0000fff, | 949 | .pvr_mask = 0xf0000fff, |
879 | .pvr_value = 0x40000481, | 950 | .pvr_value = 0x40000481, |
880 | .cpu_name = "440GP Rev. C", | 951 | .cpu_name = "440GP Rev. C", |
881 | .cpu_features = CPU_FTRS_44X, | 952 | .cpu_features = CPU_FTRS_44X, |
882 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 953 | .cpu_user_features = COMMON_USER_BOOKE, |
883 | .icache_bsize = 32, | 954 | .icache_bsize = 32, |
884 | .dcache_bsize = 32, | 955 | .dcache_bsize = 32, |
956 | .platform = "ppc440gp", | ||
885 | }, | 957 | }, |
886 | { /* 440GX Rev. A */ | 958 | { /* 440GX Rev. A */ |
887 | .pvr_mask = 0xf0000fff, | 959 | .pvr_mask = 0xf0000fff, |
888 | .pvr_value = 0x50000850, | 960 | .pvr_value = 0x50000850, |
889 | .cpu_name = "440GX Rev. A", | 961 | .cpu_name = "440GX Rev. A", |
890 | .cpu_features = CPU_FTRS_44X, | 962 | .cpu_features = CPU_FTRS_44X, |
891 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 963 | .cpu_user_features = COMMON_USER_BOOKE, |
892 | .icache_bsize = 32, | 964 | .icache_bsize = 32, |
893 | .dcache_bsize = 32, | 965 | .dcache_bsize = 32, |
966 | .platform = "ppc440", | ||
894 | }, | 967 | }, |
895 | { /* 440GX Rev. B */ | 968 | { /* 440GX Rev. B */ |
896 | .pvr_mask = 0xf0000fff, | 969 | .pvr_mask = 0xf0000fff, |
897 | .pvr_value = 0x50000851, | 970 | .pvr_value = 0x50000851, |
898 | .cpu_name = "440GX Rev. B", | 971 | .cpu_name = "440GX Rev. B", |
899 | .cpu_features = CPU_FTRS_44X, | 972 | .cpu_features = CPU_FTRS_44X, |
900 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 973 | .cpu_user_features = COMMON_USER_BOOKE, |
901 | .icache_bsize = 32, | 974 | .icache_bsize = 32, |
902 | .dcache_bsize = 32, | 975 | .dcache_bsize = 32, |
976 | .platform = "ppc440", | ||
903 | }, | 977 | }, |
904 | { /* 440GX Rev. C */ | 978 | { /* 440GX Rev. C */ |
905 | .pvr_mask = 0xf0000fff, | 979 | .pvr_mask = 0xf0000fff, |
906 | .pvr_value = 0x50000892, | 980 | .pvr_value = 0x50000892, |
907 | .cpu_name = "440GX Rev. C", | 981 | .cpu_name = "440GX Rev. C", |
908 | .cpu_features = CPU_FTRS_44X, | 982 | .cpu_features = CPU_FTRS_44X, |
909 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 983 | .cpu_user_features = COMMON_USER_BOOKE, |
910 | .icache_bsize = 32, | 984 | .icache_bsize = 32, |
911 | .dcache_bsize = 32, | 985 | .dcache_bsize = 32, |
986 | .platform = "ppc440", | ||
912 | }, | 987 | }, |
913 | { /* 440GX Rev. F */ | 988 | { /* 440GX Rev. F */ |
914 | .pvr_mask = 0xf0000fff, | 989 | .pvr_mask = 0xf0000fff, |
915 | .pvr_value = 0x50000894, | 990 | .pvr_value = 0x50000894, |
916 | .cpu_name = "440GX Rev. F", | 991 | .cpu_name = "440GX Rev. F", |
917 | .cpu_features = CPU_FTRS_44X, | 992 | .cpu_features = CPU_FTRS_44X, |
918 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 993 | .cpu_user_features = COMMON_USER_BOOKE, |
919 | .icache_bsize = 32, | 994 | .icache_bsize = 32, |
920 | .dcache_bsize = 32, | 995 | .dcache_bsize = 32, |
996 | .platform = "ppc440", | ||
921 | }, | 997 | }, |
922 | { /* 440SP Rev. A */ | 998 | { /* 440SP Rev. A */ |
923 | .pvr_mask = 0xff000fff, | 999 | .pvr_mask = 0xff000fff, |
924 | .pvr_value = 0x53000891, | 1000 | .pvr_value = 0x53000891, |
925 | .cpu_name = "440SP Rev. A", | 1001 | .cpu_name = "440SP Rev. A", |
926 | .cpu_features = CPU_FTRS_44X, | 1002 | .cpu_features = CPU_FTRS_44X, |
927 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 1003 | .cpu_user_features = COMMON_USER_BOOKE, |
928 | .icache_bsize = 32, | 1004 | .icache_bsize = 32, |
929 | .dcache_bsize = 32, | 1005 | .dcache_bsize = 32, |
1006 | .platform = "ppc440", | ||
930 | }, | 1007 | }, |
931 | { /* 440SPe Rev. A */ | 1008 | { /* 440SPe Rev. A */ |
932 | .pvr_mask = 0xff000fff, | 1009 | .pvr_mask = 0xff000fff, |
@@ -934,9 +1011,10 @@ struct cpu_spec cpu_specs[] = { | |||
934 | .cpu_name = "440SPe Rev. A", | 1011 | .cpu_name = "440SPe Rev. A", |
935 | .cpu_features = CPU_FTR_SPLIT_ID_CACHE | | 1012 | .cpu_features = CPU_FTR_SPLIT_ID_CACHE | |
936 | CPU_FTR_USE_TB, | 1013 | CPU_FTR_USE_TB, |
937 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 1014 | .cpu_user_features = COMMON_USER_BOOKE, |
938 | .icache_bsize = 32, | 1015 | .icache_bsize = 32, |
939 | .dcache_bsize = 32, | 1016 | .dcache_bsize = 32, |
1017 | .platform = "ppc440", | ||
940 | }, | 1018 | }, |
941 | #endif /* CONFIG_44x */ | 1019 | #endif /* CONFIG_44x */ |
942 | #ifdef CONFIG_FSL_BOOKE | 1020 | #ifdef CONFIG_FSL_BOOKE |
@@ -946,10 +1024,11 @@ struct cpu_spec cpu_specs[] = { | |||
946 | .cpu_name = "e200z5", | 1024 | .cpu_name = "e200z5", |
947 | /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ | 1025 | /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ |
948 | .cpu_features = CPU_FTRS_E200, | 1026 | .cpu_features = CPU_FTRS_E200, |
949 | .cpu_user_features = PPC_FEATURE_32 | | 1027 | .cpu_user_features = COMMON_USER_BOOKE | |
950 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_EFP_SINGLE | | 1028 | PPC_FEATURE_HAS_EFP_SINGLE | |
951 | PPC_FEATURE_UNIFIED_CACHE, | 1029 | PPC_FEATURE_UNIFIED_CACHE, |
952 | .dcache_bsize = 32, | 1030 | .dcache_bsize = 32, |
1031 | .platform = "ppc5554", | ||
953 | }, | 1032 | }, |
954 | { /* e200z6 */ | 1033 | { /* e200z6 */ |
955 | .pvr_mask = 0xfff00000, | 1034 | .pvr_mask = 0xfff00000, |
@@ -957,11 +1036,12 @@ struct cpu_spec cpu_specs[] = { | |||
957 | .cpu_name = "e200z6", | 1036 | .cpu_name = "e200z6", |
958 | /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ | 1037 | /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ |
959 | .cpu_features = CPU_FTRS_E200, | 1038 | .cpu_features = CPU_FTRS_E200, |
960 | .cpu_user_features = PPC_FEATURE_32 | | 1039 | .cpu_user_features = COMMON_USER_BOOKE | |
961 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | | 1040 | PPC_FEATURE_SPE_COMP | |
962 | PPC_FEATURE_HAS_EFP_SINGLE | | 1041 | PPC_FEATURE_HAS_EFP_SINGLE | |
963 | PPC_FEATURE_UNIFIED_CACHE, | 1042 | PPC_FEATURE_UNIFIED_CACHE, |
964 | .dcache_bsize = 32, | 1043 | .dcache_bsize = 32, |
1044 | .platform = "ppc5554", | ||
965 | }, | 1045 | }, |
966 | { /* e500 */ | 1046 | { /* e500 */ |
967 | .pvr_mask = 0xffff0000, | 1047 | .pvr_mask = 0xffff0000, |
@@ -969,14 +1049,15 @@ struct cpu_spec cpu_specs[] = { | |||
969 | .cpu_name = "e500", | 1049 | .cpu_name = "e500", |
970 | /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ | 1050 | /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ |
971 | .cpu_features = CPU_FTRS_E500, | 1051 | .cpu_features = CPU_FTRS_E500, |
972 | .cpu_user_features = PPC_FEATURE_32 | | 1052 | .cpu_user_features = COMMON_USER_BOOKE | |
973 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | | 1053 | PPC_FEATURE_SPE_COMP | |
974 | PPC_FEATURE_HAS_EFP_SINGLE, | 1054 | PPC_FEATURE_HAS_EFP_SINGLE, |
975 | .icache_bsize = 32, | 1055 | .icache_bsize = 32, |
976 | .dcache_bsize = 32, | 1056 | .dcache_bsize = 32, |
977 | .num_pmcs = 4, | 1057 | .num_pmcs = 4, |
978 | .oprofile_cpu_type = "ppc/e500", | 1058 | .oprofile_cpu_type = "ppc/e500", |
979 | .oprofile_type = BOOKE, | 1059 | .oprofile_type = PPC_OPROFILE_BOOKE, |
1060 | .platform = "ppc8540", | ||
980 | }, | 1061 | }, |
981 | { /* e500v2 */ | 1062 | { /* e500v2 */ |
982 | .pvr_mask = 0xffff0000, | 1063 | .pvr_mask = 0xffff0000, |
@@ -984,14 +1065,16 @@ struct cpu_spec cpu_specs[] = { | |||
984 | .cpu_name = "e500v2", | 1065 | .cpu_name = "e500v2", |
985 | /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ | 1066 | /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ |
986 | .cpu_features = CPU_FTRS_E500_2, | 1067 | .cpu_features = CPU_FTRS_E500_2, |
987 | .cpu_user_features = PPC_FEATURE_32 | | 1068 | .cpu_user_features = COMMON_USER_BOOKE | |
988 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | | 1069 | PPC_FEATURE_SPE_COMP | |
989 | PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_HAS_EFP_DOUBLE, | 1070 | PPC_FEATURE_HAS_EFP_SINGLE | |
1071 | PPC_FEATURE_HAS_EFP_DOUBLE, | ||
990 | .icache_bsize = 32, | 1072 | .icache_bsize = 32, |
991 | .dcache_bsize = 32, | 1073 | .dcache_bsize = 32, |
992 | .num_pmcs = 4, | 1074 | .num_pmcs = 4, |
993 | .oprofile_cpu_type = "ppc/e500", | 1075 | .oprofile_cpu_type = "ppc/e500", |
994 | .oprofile_type = BOOKE, | 1076 | .oprofile_type = PPC_OPROFILE_BOOKE, |
1077 | .platform = "ppc8548", | ||
995 | }, | 1078 | }, |
996 | #endif | 1079 | #endif |
997 | #if !CLASSIC_PPC | 1080 | #if !CLASSIC_PPC |
@@ -1003,6 +1086,7 @@ struct cpu_spec cpu_specs[] = { | |||
1003 | .cpu_user_features = PPC_FEATURE_32, | 1086 | .cpu_user_features = PPC_FEATURE_32, |
1004 | .icache_bsize = 32, | 1087 | .icache_bsize = 32, |
1005 | .dcache_bsize = 32, | 1088 | .dcache_bsize = 32, |
1089 | .platform = "powerpc", | ||
1006 | } | 1090 | } |
1007 | #endif /* !CLASSIC_PPC */ | 1091 | #endif /* !CLASSIC_PPC */ |
1008 | #endif /* CONFIG_PPC32 */ | 1092 | #endif /* CONFIG_PPC32 */ |
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 036b71d2adfc..d8da2a35c0a4 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -988,7 +988,7 @@ _GLOBAL(enter_rtas) | |||
988 | stwu r1,-INT_FRAME_SIZE(r1) | 988 | stwu r1,-INT_FRAME_SIZE(r1) |
989 | mflr r0 | 989 | mflr r0 |
990 | stw r0,INT_FRAME_SIZE+4(r1) | 990 | stw r0,INT_FRAME_SIZE+4(r1) |
991 | LOADADDR(r4, rtas) | 991 | LOAD_REG_ADDR(r4, rtas) |
992 | lis r6,1f@ha /* physical return address for rtas */ | 992 | lis r6,1f@ha /* physical return address for rtas */ |
993 | addi r6,r6,1f@l | 993 | addi r6,r6,1f@l |
994 | tophys(r6,r6) | 994 | tophys(r6,r6) |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index aacebb33e98a..542036318866 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -511,7 +511,8 @@ restore: | |||
511 | cmpdi 0,r5,0 | 511 | cmpdi 0,r5,0 |
512 | beq 4f | 512 | beq 4f |
513 | /* Check for pending interrupts (iSeries) */ | 513 | /* Check for pending interrupts (iSeries) */ |
514 | ld r3,PACALPPACA+LPPACAANYINT(r13) | 514 | ld r3,PACALPPACAPTR(r13) |
515 | ld r3,LPPACAANYINT(r3) | ||
515 | cmpdi r3,0 | 516 | cmpdi r3,0 |
516 | beq+ 4f /* skip do_IRQ if no interrupts */ | 517 | beq+ 4f /* skip do_IRQ if no interrupts */ |
517 | 518 | ||
@@ -689,9 +690,8 @@ _GLOBAL(enter_rtas) | |||
689 | std r6,PACASAVEDMSR(r13) | 690 | std r6,PACASAVEDMSR(r13) |
690 | 691 | ||
691 | /* Setup our real return addr */ | 692 | /* Setup our real return addr */ |
692 | SET_REG_TO_LABEL(r4,.rtas_return_loc) | 693 | LOAD_REG_ADDR(r4,.rtas_return_loc) |
693 | SET_REG_TO_CONST(r9,PAGE_OFFSET) | 694 | clrldi r4,r4,2 /* convert to realmode address */ |
694 | sub r4,r4,r9 | ||
695 | mtlr r4 | 695 | mtlr r4 |
696 | 696 | ||
697 | li r0,0 | 697 | li r0,0 |
@@ -706,7 +706,7 @@ _GLOBAL(enter_rtas) | |||
706 | sync /* disable interrupts so SRR0/1 */ | 706 | sync /* disable interrupts so SRR0/1 */ |
707 | mtmsrd r0 /* don't get trashed */ | 707 | mtmsrd r0 /* don't get trashed */ |
708 | 708 | ||
709 | SET_REG_TO_LABEL(r4,rtas) | 709 | LOAD_REG_ADDR(r4, rtas) |
710 | ld r5,RTASENTRY(r4) /* get the rtas->entry value */ | 710 | ld r5,RTASENTRY(r4) /* get the rtas->entry value */ |
711 | ld r4,RTASBASE(r4) /* get the rtas->base value */ | 711 | ld r4,RTASBASE(r4) /* get the rtas->base value */ |
712 | 712 | ||
@@ -718,8 +718,7 @@ _GLOBAL(enter_rtas) | |||
718 | _STATIC(rtas_return_loc) | 718 | _STATIC(rtas_return_loc) |
719 | /* relocation is off at this point */ | 719 | /* relocation is off at this point */ |
720 | mfspr r4,SPRN_SPRG3 /* Get PACA */ | 720 | mfspr r4,SPRN_SPRG3 /* Get PACA */ |
721 | SET_REG_TO_CONST(r5, PAGE_OFFSET) | 721 | clrldi r4,r4,2 /* convert to realmode address */ |
722 | sub r4,r4,r5 /* RELOC the PACA base pointer */ | ||
723 | 722 | ||
724 | mfmsr r6 | 723 | mfmsr r6 |
725 | li r0,MSR_RI | 724 | li r0,MSR_RI |
@@ -728,7 +727,7 @@ _STATIC(rtas_return_loc) | |||
728 | mtmsrd r6 | 727 | mtmsrd r6 |
729 | 728 | ||
730 | ld r1,PACAR1(r4) /* Restore our SP */ | 729 | ld r1,PACAR1(r4) /* Restore our SP */ |
731 | LOADADDR(r3,.rtas_restore_regs) | 730 | LOAD_REG_IMMEDIATE(r3,.rtas_restore_regs) |
732 | ld r4,PACASAVEDMSR(r4) /* Restore our MSR */ | 731 | ld r4,PACASAVEDMSR(r4) /* Restore our MSR */ |
733 | 732 | ||
734 | mtspr SPRN_SRR0,r3 | 733 | mtspr SPRN_SRR0,r3 |
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index b780b42c95fc..e4362dfa37fb 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S | |||
@@ -39,9 +39,9 @@ _GLOBAL(load_up_fpu) | |||
39 | * to another. Instead we call giveup_fpu in switch_to. | 39 | * to another. Instead we call giveup_fpu in switch_to. |
40 | */ | 40 | */ |
41 | #ifndef CONFIG_SMP | 41 | #ifndef CONFIG_SMP |
42 | LOADBASE(r3, last_task_used_math) | 42 | LOAD_REG_ADDRBASE(r3, last_task_used_math) |
43 | toreal(r3) | 43 | toreal(r3) |
44 | PPC_LL r4,OFF(last_task_used_math)(r3) | 44 | PPC_LL r4,ADDROFF(last_task_used_math)(r3) |
45 | PPC_LCMPI 0,r4,0 | 45 | PPC_LCMPI 0,r4,0 |
46 | beq 1f | 46 | beq 1f |
47 | toreal(r4) | 47 | toreal(r4) |
@@ -77,7 +77,7 @@ _GLOBAL(load_up_fpu) | |||
77 | #ifndef CONFIG_SMP | 77 | #ifndef CONFIG_SMP |
78 | subi r4,r5,THREAD | 78 | subi r4,r5,THREAD |
79 | fromreal(r4) | 79 | fromreal(r4) |
80 | PPC_STL r4,OFF(last_task_used_math)(r3) | 80 | PPC_STL r4,ADDROFF(last_task_used_math)(r3) |
81 | #endif /* CONFIG_SMP */ | 81 | #endif /* CONFIG_SMP */ |
82 | /* restore registers and return */ | 82 | /* restore registers and return */ |
83 | /* we haven't used ctr or xer or lr */ | 83 | /* we haven't used ctr or xer or lr */ |
@@ -113,8 +113,8 @@ _GLOBAL(giveup_fpu) | |||
113 | 1: | 113 | 1: |
114 | #ifndef CONFIG_SMP | 114 | #ifndef CONFIG_SMP |
115 | li r5,0 | 115 | li r5,0 |
116 | LOADBASE(r4,last_task_used_math) | 116 | LOAD_REG_ADDRBASE(r4,last_task_used_math) |
117 | PPC_STL r5,OFF(last_task_used_math)(r4) | 117 | PPC_STL r5,ADDROFF(last_task_used_math)(r4) |
118 | #endif /* CONFIG_SMP */ | 118 | #endif /* CONFIG_SMP */ |
119 | blr | 119 | blr |
120 | 120 | ||
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 1c066d125375..308268466342 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -154,12 +154,12 @@ _GLOBAL(__secondary_hold) | |||
154 | bne 100b | 154 | bne 100b |
155 | 155 | ||
156 | #ifdef CONFIG_HMT | 156 | #ifdef CONFIG_HMT |
157 | LOADADDR(r4, .hmt_init) | 157 | SET_REG_IMMEDIATE(r4, .hmt_init) |
158 | mtctr r4 | 158 | mtctr r4 |
159 | bctr | 159 | bctr |
160 | #else | 160 | #else |
161 | #ifdef CONFIG_SMP | 161 | #ifdef CONFIG_SMP |
162 | LOADADDR(r4, .pSeries_secondary_smp_init) | 162 | LOAD_REG_IMMEDIATE(r4, .pSeries_secondary_smp_init) |
163 | mtctr r4 | 163 | mtctr r4 |
164 | mr r3,r24 | 164 | mr r3,r24 |
165 | bctr | 165 | bctr |
@@ -205,9 +205,10 @@ exception_marker: | |||
205 | #define EX_LR 72 | 205 | #define EX_LR 72 |
206 | 206 | ||
207 | /* | 207 | /* |
208 | * We're short on space and time in the exception prolog, so we can't use | 208 | * We're short on space and time in the exception prolog, so we can't |
209 | * the normal LOADADDR macro. Normally we just need the low halfword of the | 209 | * use the normal SET_REG_IMMEDIATE macro. Normally we just need the |
210 | * address, but for Kdump we need the whole low word. | 210 | * low halfword of the address, but for Kdump we need the whole low |
211 | * word. | ||
211 | */ | 212 | */ |
212 | #ifdef CONFIG_CRASH_DUMP | 213 | #ifdef CONFIG_CRASH_DUMP |
213 | #define LOAD_HANDLER(reg, label) \ | 214 | #define LOAD_HANDLER(reg, label) \ |
@@ -254,8 +255,9 @@ exception_marker: | |||
254 | 255 | ||
255 | #define EXCEPTION_PROLOG_ISERIES_2 \ | 256 | #define EXCEPTION_PROLOG_ISERIES_2 \ |
256 | mfmsr r10; \ | 257 | mfmsr r10; \ |
257 | ld r11,PACALPPACA+LPPACASRR0(r13); \ | 258 | ld r12,PACALPPACAPTR(r13); \ |
258 | ld r12,PACALPPACA+LPPACASRR1(r13); \ | 259 | ld r11,LPPACASRR0(r12); \ |
260 | ld r12,LPPACASRR1(r12); \ | ||
259 | ori r10,r10,MSR_RI; \ | 261 | ori r10,r10,MSR_RI; \ |
260 | mtmsrd r10,1 | 262 | mtmsrd r10,1 |
261 | 263 | ||
@@ -634,7 +636,8 @@ data_access_slb_iSeries: | |||
634 | std r12,PACA_EXSLB+EX_R12(r13) | 636 | std r12,PACA_EXSLB+EX_R12(r13) |
635 | mfspr r10,SPRN_SPRG1 | 637 | mfspr r10,SPRN_SPRG1 |
636 | std r10,PACA_EXSLB+EX_R13(r13) | 638 | std r10,PACA_EXSLB+EX_R13(r13) |
637 | ld r12,PACALPPACA+LPPACASRR1(r13); | 639 | ld r12,PACALPPACAPTR(r13) |
640 | ld r12,LPPACASRR1(r12) | ||
638 | b .slb_miss_realmode | 641 | b .slb_miss_realmode |
639 | 642 | ||
640 | STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN) | 643 | STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN) |
@@ -644,7 +647,8 @@ instruction_access_slb_iSeries: | |||
644 | mtspr SPRN_SPRG1,r13 /* save r13 */ | 647 | mtspr SPRN_SPRG1,r13 /* save r13 */ |
645 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | 648 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ |
646 | std r3,PACA_EXSLB+EX_R3(r13) | 649 | std r3,PACA_EXSLB+EX_R3(r13) |
647 | ld r3,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ | 650 | ld r3,PACALPPACAPTR(r13) |
651 | ld r3,LPPACASRR0(r3) /* get SRR0 value */ | ||
648 | std r9,PACA_EXSLB+EX_R9(r13) | 652 | std r9,PACA_EXSLB+EX_R9(r13) |
649 | mfcr r9 | 653 | mfcr r9 |
650 | #ifdef __DISABLED__ | 654 | #ifdef __DISABLED__ |
@@ -656,7 +660,8 @@ instruction_access_slb_iSeries: | |||
656 | std r12,PACA_EXSLB+EX_R12(r13) | 660 | std r12,PACA_EXSLB+EX_R12(r13) |
657 | mfspr r10,SPRN_SPRG1 | 661 | mfspr r10,SPRN_SPRG1 |
658 | std r10,PACA_EXSLB+EX_R13(r13) | 662 | std r10,PACA_EXSLB+EX_R13(r13) |
659 | ld r12,PACALPPACA+LPPACASRR1(r13); | 663 | ld r12,PACALPPACAPTR(r13) |
664 | ld r12,LPPACASRR1(r12) | ||
660 | b .slb_miss_realmode | 665 | b .slb_miss_realmode |
661 | 666 | ||
662 | #ifdef __DISABLED__ | 667 | #ifdef __DISABLED__ |
@@ -713,7 +718,7 @@ system_reset_iSeries: | |||
713 | lbz r23,PACAPROCSTART(r13) /* Test if this processor | 718 | lbz r23,PACAPROCSTART(r13) /* Test if this processor |
714 | * should start */ | 719 | * should start */ |
715 | sync | 720 | sync |
716 | LOADADDR(r3,current_set) | 721 | LOAD_REG_IMMEDIATE(r3,current_set) |
717 | sldi r28,r24,3 /* get current_set[cpu#] */ | 722 | sldi r28,r24,3 /* get current_set[cpu#] */ |
718 | ldx r3,r3,r28 | 723 | ldx r3,r3,r28 |
719 | addi r1,r3,THREAD_SIZE | 724 | addi r1,r3,THREAD_SIZE |
@@ -745,17 +750,19 @@ iSeries_secondary_smp_loop: | |||
745 | .globl decrementer_iSeries_masked | 750 | .globl decrementer_iSeries_masked |
746 | decrementer_iSeries_masked: | 751 | decrementer_iSeries_masked: |
747 | li r11,1 | 752 | li r11,1 |
748 | stb r11,PACALPPACA+LPPACADECRINT(r13) | 753 | ld r12,PACALPPACAPTR(r13) |
749 | LOADBASE(r12,tb_ticks_per_jiffy) | 754 | stb r11,LPPACADECRINT(r12) |
750 | lwz r12,OFF(tb_ticks_per_jiffy)(r12) | 755 | LOAD_REG_ADDRBASE(r12,tb_ticks_per_jiffy) |
756 | lwz r12,ADDROFF(tb_ticks_per_jiffy)(r12) | ||
751 | mtspr SPRN_DEC,r12 | 757 | mtspr SPRN_DEC,r12 |
752 | /* fall through */ | 758 | /* fall through */ |
753 | 759 | ||
754 | .globl hardware_interrupt_iSeries_masked | 760 | .globl hardware_interrupt_iSeries_masked |
755 | hardware_interrupt_iSeries_masked: | 761 | hardware_interrupt_iSeries_masked: |
756 | mtcrf 0x80,r9 /* Restore regs */ | 762 | mtcrf 0x80,r9 /* Restore regs */ |
757 | ld r11,PACALPPACA+LPPACASRR0(r13) | 763 | ld r12,PACALPPACAPTR(r13) |
758 | ld r12,PACALPPACA+LPPACASRR1(r13) | 764 | ld r11,LPPACASRR0(r12) |
765 | ld r12,LPPACASRR1(r12) | ||
759 | mtspr SPRN_SRR0,r11 | 766 | mtspr SPRN_SRR0,r11 |
760 | mtspr SPRN_SRR1,r12 | 767 | mtspr SPRN_SRR1,r12 |
761 | ld r9,PACA_EXGEN+EX_R9(r13) | 768 | ld r9,PACA_EXGEN+EX_R9(r13) |
@@ -994,7 +1001,8 @@ _GLOBAL(slb_miss_realmode) | |||
994 | ld r3,PACA_EXSLB+EX_R3(r13) | 1001 | ld r3,PACA_EXSLB+EX_R3(r13) |
995 | lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ | 1002 | lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ |
996 | #ifdef CONFIG_PPC_ISERIES | 1003 | #ifdef CONFIG_PPC_ISERIES |
997 | ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ | 1004 | ld r11,PACALPPACAPTR(r13) |
1005 | ld r11,LPPACASRR0(r11) /* get SRR0 value */ | ||
998 | #endif /* CONFIG_PPC_ISERIES */ | 1006 | #endif /* CONFIG_PPC_ISERIES */ |
999 | 1007 | ||
1000 | mtlr r10 | 1008 | mtlr r10 |
@@ -1412,7 +1420,7 @@ _GLOBAL(pSeries_secondary_smp_init) | |||
1412 | * physical cpu id in r24, we need to search the pacas to find | 1420 | * physical cpu id in r24, we need to search the pacas to find |
1413 | * which logical id maps to our physical one. | 1421 | * which logical id maps to our physical one. |
1414 | */ | 1422 | */ |
1415 | LOADADDR(r13, paca) /* Get base vaddr of paca array */ | 1423 | LOAD_REG_IMMEDIATE(r13, paca) /* Get base vaddr of paca array */ |
1416 | li r5,0 /* logical cpu id */ | 1424 | li r5,0 /* logical cpu id */ |
1417 | 1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ | 1425 | 1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ |
1418 | cmpw r6,r24 /* Compare to our id */ | 1426 | cmpw r6,r24 /* Compare to our id */ |
@@ -1446,8 +1454,8 @@ _GLOBAL(pSeries_secondary_smp_init) | |||
1446 | #ifdef CONFIG_PPC_ISERIES | 1454 | #ifdef CONFIG_PPC_ISERIES |
1447 | _STATIC(__start_initialization_iSeries) | 1455 | _STATIC(__start_initialization_iSeries) |
1448 | /* Clear out the BSS */ | 1456 | /* Clear out the BSS */ |
1449 | LOADADDR(r11,__bss_stop) | 1457 | LOAD_REG_IMMEDIATE(r11,__bss_stop) |
1450 | LOADADDR(r8,__bss_start) | 1458 | LOAD_REG_IMMEDIATE(r8,__bss_start) |
1451 | sub r11,r11,r8 /* bss size */ | 1459 | sub r11,r11,r8 /* bss size */ |
1452 | addi r11,r11,7 /* round up to an even double word */ | 1460 | addi r11,r11,7 /* round up to an even double word */ |
1453 | rldicl. r11,r11,61,3 /* shift right by 3 */ | 1461 | rldicl. r11,r11,61,3 /* shift right by 3 */ |
@@ -1458,17 +1466,17 @@ _STATIC(__start_initialization_iSeries) | |||
1458 | 3: stdu r0,8(r8) | 1466 | 3: stdu r0,8(r8) |
1459 | bdnz 3b | 1467 | bdnz 3b |
1460 | 4: | 1468 | 4: |
1461 | LOADADDR(r1,init_thread_union) | 1469 | LOAD_REG_IMMEDIATE(r1,init_thread_union) |
1462 | addi r1,r1,THREAD_SIZE | 1470 | addi r1,r1,THREAD_SIZE |
1463 | li r0,0 | 1471 | li r0,0 |
1464 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | 1472 | stdu r0,-STACK_FRAME_OVERHEAD(r1) |
1465 | 1473 | ||
1466 | LOADADDR(r3,cpu_specs) | 1474 | LOAD_REG_IMMEDIATE(r3,cpu_specs) |
1467 | LOADADDR(r4,cur_cpu_spec) | 1475 | LOAD_REG_IMMEDIATE(r4,cur_cpu_spec) |
1468 | li r5,0 | 1476 | li r5,0 |
1469 | bl .identify_cpu | 1477 | bl .identify_cpu |
1470 | 1478 | ||
1471 | LOADADDR(r2,__toc_start) | 1479 | LOAD_REG_IMMEDIATE(r2,__toc_start) |
1472 | addi r2,r2,0x4000 | 1480 | addi r2,r2,0x4000 |
1473 | addi r2,r2,0x4000 | 1481 | addi r2,r2,0x4000 |
1474 | 1482 | ||
@@ -1528,7 +1536,7 @@ _GLOBAL(__start_initialization_multiplatform) | |||
1528 | li r24,0 | 1536 | li r24,0 |
1529 | 1537 | ||
1530 | /* Switch off MMU if not already */ | 1538 | /* Switch off MMU if not already */ |
1531 | LOADADDR(r4, .__after_prom_start - KERNELBASE) | 1539 | LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE) |
1532 | add r4,r4,r30 | 1540 | add r4,r4,r30 |
1533 | bl .__mmu_off | 1541 | bl .__mmu_off |
1534 | b .__after_prom_start | 1542 | b .__after_prom_start |
@@ -1548,7 +1556,7 @@ _STATIC(__boot_from_prom) | |||
1548 | /* put a relocation offset into r3 */ | 1556 | /* put a relocation offset into r3 */ |
1549 | bl .reloc_offset | 1557 | bl .reloc_offset |
1550 | 1558 | ||
1551 | LOADADDR(r2,__toc_start) | 1559 | LOAD_REG_IMMEDIATE(r2,__toc_start) |
1552 | addi r2,r2,0x4000 | 1560 | addi r2,r2,0x4000 |
1553 | addi r2,r2,0x4000 | 1561 | addi r2,r2,0x4000 |
1554 | 1562 | ||
@@ -1588,9 +1596,9 @@ _STATIC(__after_prom_start) | |||
1588 | */ | 1596 | */ |
1589 | bl .reloc_offset | 1597 | bl .reloc_offset |
1590 | mr r26,r3 | 1598 | mr r26,r3 |
1591 | SET_REG_TO_CONST(r27,KERNELBASE) | 1599 | LOAD_REG_IMMEDIATE(r27, KERNELBASE) |
1592 | 1600 | ||
1593 | LOADADDR(r3, PHYSICAL_START) /* target addr */ | 1601 | LOAD_REG_IMMEDIATE(r3, PHYSICAL_START) /* target addr */ |
1594 | 1602 | ||
1595 | // XXX FIXME: Use phys returned by OF (r30) | 1603 | // XXX FIXME: Use phys returned by OF (r30) |
1596 | add r4,r27,r26 /* source addr */ | 1604 | add r4,r27,r26 /* source addr */ |
@@ -1598,7 +1606,7 @@ _STATIC(__after_prom_start) | |||
1598 | /* i.e. where we are running */ | 1606 | /* i.e. where we are running */ |
1599 | /* the source addr */ | 1607 | /* the source addr */ |
1600 | 1608 | ||
1601 | LOADADDR(r5,copy_to_here) /* # bytes of memory to copy */ | 1609 | LOAD_REG_IMMEDIATE(r5,copy_to_here) /* # bytes of memory to copy */ |
1602 | sub r5,r5,r27 | 1610 | sub r5,r5,r27 |
1603 | 1611 | ||
1604 | li r6,0x100 /* Start offset, the first 0x100 */ | 1612 | li r6,0x100 /* Start offset, the first 0x100 */ |
@@ -1608,11 +1616,11 @@ _STATIC(__after_prom_start) | |||
1608 | /* this includes the code being */ | 1616 | /* this includes the code being */ |
1609 | /* executed here. */ | 1617 | /* executed here. */ |
1610 | 1618 | ||
1611 | LOADADDR(r0, 4f) /* Jump to the copy of this code */ | 1619 | LOAD_REG_IMMEDIATE(r0, 4f) /* Jump to the copy of this code */ |
1612 | mtctr r0 /* that we just made/relocated */ | 1620 | mtctr r0 /* that we just made/relocated */ |
1613 | bctr | 1621 | bctr |
1614 | 1622 | ||
1615 | 4: LOADADDR(r5,klimit) | 1623 | 4: LOAD_REG_IMMEDIATE(r5,klimit) |
1616 | add r5,r5,r26 | 1624 | add r5,r5,r26 |
1617 | ld r5,0(r5) /* get the value of klimit */ | 1625 | ld r5,0(r5) /* get the value of klimit */ |
1618 | sub r5,r5,r27 | 1626 | sub r5,r5,r27 |
@@ -1694,7 +1702,7 @@ _GLOBAL(pmac_secondary_start) | |||
1694 | mtmsrd r3 /* RI on */ | 1702 | mtmsrd r3 /* RI on */ |
1695 | 1703 | ||
1696 | /* Set up a paca value for this processor. */ | 1704 | /* Set up a paca value for this processor. */ |
1697 | LOADADDR(r4, paca) /* Get base vaddr of paca array */ | 1705 | LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */ |
1698 | mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ | 1706 | mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ |
1699 | add r13,r13,r4 /* for this processor. */ | 1707 | add r13,r13,r4 /* for this processor. */ |
1700 | mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ | 1708 | mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ |
@@ -1731,7 +1739,7 @@ _GLOBAL(__secondary_start) | |||
1731 | bl .early_setup_secondary | 1739 | bl .early_setup_secondary |
1732 | 1740 | ||
1733 | /* Initialize the kernel stack. Just a repeat for iSeries. */ | 1741 | /* Initialize the kernel stack. Just a repeat for iSeries. */ |
1734 | LOADADDR(r3,current_set) | 1742 | LOAD_REG_ADDR(r3, current_set) |
1735 | sldi r28,r24,3 /* get current_set[cpu#] */ | 1743 | sldi r28,r24,3 /* get current_set[cpu#] */ |
1736 | ldx r1,r3,r28 | 1744 | ldx r1,r3,r28 |
1737 | addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD | 1745 | addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD |
@@ -1742,8 +1750,8 @@ _GLOBAL(__secondary_start) | |||
1742 | mtlr r7 | 1750 | mtlr r7 |
1743 | 1751 | ||
1744 | /* enable MMU and jump to start_secondary */ | 1752 | /* enable MMU and jump to start_secondary */ |
1745 | LOADADDR(r3,.start_secondary_prolog) | 1753 | LOAD_REG_ADDR(r3, .start_secondary_prolog) |
1746 | SET_REG_TO_CONST(r4, MSR_KERNEL) | 1754 | LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) |
1747 | #ifdef DO_SOFT_DISABLE | 1755 | #ifdef DO_SOFT_DISABLE |
1748 | ori r4,r4,MSR_EE | 1756 | ori r4,r4,MSR_EE |
1749 | #endif | 1757 | #endif |
@@ -1792,8 +1800,8 @@ _STATIC(start_here_multiplatform) | |||
1792 | * be detached from the kernel completely. Besides, we need | 1800 | * be detached from the kernel completely. Besides, we need |
1793 | * to clear it now for kexec-style entry. | 1801 | * to clear it now for kexec-style entry. |
1794 | */ | 1802 | */ |
1795 | LOADADDR(r11,__bss_stop) | 1803 | LOAD_REG_IMMEDIATE(r11,__bss_stop) |
1796 | LOADADDR(r8,__bss_start) | 1804 | LOAD_REG_IMMEDIATE(r8,__bss_start) |
1797 | sub r11,r11,r8 /* bss size */ | 1805 | sub r11,r11,r8 /* bss size */ |
1798 | addi r11,r11,7 /* round up to an even double word */ | 1806 | addi r11,r11,7 /* round up to an even double word */ |
1799 | rldicl. r11,r11,61,3 /* shift right by 3 */ | 1807 | rldicl. r11,r11,61,3 /* shift right by 3 */ |
@@ -1831,7 +1839,7 @@ _STATIC(start_here_multiplatform) | |||
1831 | /* up the htab. This is done because we have relocated the */ | 1839 | /* up the htab. This is done because we have relocated the */ |
1832 | /* kernel but are still running in real mode. */ | 1840 | /* kernel but are still running in real mode. */ |
1833 | 1841 | ||
1834 | LOADADDR(r3,init_thread_union) | 1842 | LOAD_REG_IMMEDIATE(r3,init_thread_union) |
1835 | add r3,r3,r26 | 1843 | add r3,r3,r26 |
1836 | 1844 | ||
1837 | /* set up a stack pointer (physical address) */ | 1845 | /* set up a stack pointer (physical address) */ |
@@ -1840,14 +1848,14 @@ _STATIC(start_here_multiplatform) | |||
1840 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | 1848 | stdu r0,-STACK_FRAME_OVERHEAD(r1) |
1841 | 1849 | ||
1842 | /* set up the TOC (physical address) */ | 1850 | /* set up the TOC (physical address) */ |
1843 | LOADADDR(r2,__toc_start) | 1851 | LOAD_REG_IMMEDIATE(r2,__toc_start) |
1844 | addi r2,r2,0x4000 | 1852 | addi r2,r2,0x4000 |
1845 | addi r2,r2,0x4000 | 1853 | addi r2,r2,0x4000 |
1846 | add r2,r2,r26 | 1854 | add r2,r2,r26 |
1847 | 1855 | ||
1848 | LOADADDR(r3,cpu_specs) | 1856 | LOAD_REG_IMMEDIATE(r3, cpu_specs) |
1849 | add r3,r3,r26 | 1857 | add r3,r3,r26 |
1850 | LOADADDR(r4,cur_cpu_spec) | 1858 | LOAD_REG_IMMEDIATE(r4,cur_cpu_spec) |
1851 | add r4,r4,r26 | 1859 | add r4,r4,r26 |
1852 | mr r5,r26 | 1860 | mr r5,r26 |
1853 | bl .identify_cpu | 1861 | bl .identify_cpu |
@@ -1863,11 +1871,11 @@ _STATIC(start_here_multiplatform) | |||
1863 | * nowhere it can be initialized differently before we reach this | 1871 | * nowhere it can be initialized differently before we reach this |
1864 | * code | 1872 | * code |
1865 | */ | 1873 | */ |
1866 | LOADADDR(r27, boot_cpuid) | 1874 | LOAD_REG_IMMEDIATE(r27, boot_cpuid) |
1867 | add r27,r27,r26 | 1875 | add r27,r27,r26 |
1868 | lwz r27,0(r27) | 1876 | lwz r27,0(r27) |
1869 | 1877 | ||
1870 | LOADADDR(r24, paca) /* Get base vaddr of paca array */ | 1878 | LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */ |
1871 | mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */ | 1879 | mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */ |
1872 | add r13,r13,r24 /* for this processor. */ | 1880 | add r13,r13,r24 /* for this processor. */ |
1873 | add r13,r13,r26 /* convert to physical addr */ | 1881 | add r13,r13,r26 /* convert to physical addr */ |
@@ -1880,8 +1888,8 @@ _STATIC(start_here_multiplatform) | |||
1880 | mr r3,r31 | 1888 | mr r3,r31 |
1881 | bl .early_setup | 1889 | bl .early_setup |
1882 | 1890 | ||
1883 | LOADADDR(r3,.start_here_common) | 1891 | LOAD_REG_IMMEDIATE(r3, .start_here_common) |
1884 | SET_REG_TO_CONST(r4, MSR_KERNEL) | 1892 | LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) |
1885 | mtspr SPRN_SRR0,r3 | 1893 | mtspr SPRN_SRR0,r3 |
1886 | mtspr SPRN_SRR1,r4 | 1894 | mtspr SPRN_SRR1,r4 |
1887 | rfid | 1895 | rfid |
@@ -1895,7 +1903,7 @@ _STATIC(start_here_common) | |||
1895 | /* The following code sets up the SP and TOC now that we are */ | 1903 | /* The following code sets up the SP and TOC now that we are */ |
1896 | /* running with translation enabled. */ | 1904 | /* running with translation enabled. */ |
1897 | 1905 | ||
1898 | LOADADDR(r3,init_thread_union) | 1906 | LOAD_REG_IMMEDIATE(r3,init_thread_union) |
1899 | 1907 | ||
1900 | /* set up the stack */ | 1908 | /* set up the stack */ |
1901 | addi r1,r3,THREAD_SIZE | 1909 | addi r1,r3,THREAD_SIZE |
@@ -1908,16 +1916,16 @@ _STATIC(start_here_common) | |||
1908 | li r3,0 | 1916 | li r3,0 |
1909 | bl .do_cpu_ftr_fixups | 1917 | bl .do_cpu_ftr_fixups |
1910 | 1918 | ||
1911 | LOADADDR(r26, boot_cpuid) | 1919 | LOAD_REG_IMMEDIATE(r26, boot_cpuid) |
1912 | lwz r26,0(r26) | 1920 | lwz r26,0(r26) |
1913 | 1921 | ||
1914 | LOADADDR(r24, paca) /* Get base vaddr of paca array */ | 1922 | LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */ |
1915 | mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */ | 1923 | mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */ |
1916 | add r13,r13,r24 /* for this processor. */ | 1924 | add r13,r13,r24 /* for this processor. */ |
1917 | mtspr SPRN_SPRG3,r13 | 1925 | mtspr SPRN_SPRG3,r13 |
1918 | 1926 | ||
1919 | /* ptr to current */ | 1927 | /* ptr to current */ |
1920 | LOADADDR(r4,init_task) | 1928 | LOAD_REG_IMMEDIATE(r4, init_task) |
1921 | std r4,PACACURRENT(r13) | 1929 | std r4,PACACURRENT(r13) |
1922 | 1930 | ||
1923 | /* Load the TOC */ | 1931 | /* Load the TOC */ |
@@ -1940,7 +1948,7 @@ _STATIC(start_here_common) | |||
1940 | 1948 | ||
1941 | _GLOBAL(hmt_init) | 1949 | _GLOBAL(hmt_init) |
1942 | #ifdef CONFIG_HMT | 1950 | #ifdef CONFIG_HMT |
1943 | LOADADDR(r5, hmt_thread_data) | 1951 | LOAD_REG_IMMEDIATE(r5, hmt_thread_data) |
1944 | mfspr r7,SPRN_PVR | 1952 | mfspr r7,SPRN_PVR |
1945 | srwi r7,r7,16 | 1953 | srwi r7,r7,16 |
1946 | cmpwi r7,0x34 /* Pulsar */ | 1954 | cmpwi r7,0x34 /* Pulsar */ |
@@ -1961,7 +1969,7 @@ _GLOBAL(hmt_init) | |||
1961 | b 101f | 1969 | b 101f |
1962 | 1970 | ||
1963 | __hmt_secondary_hold: | 1971 | __hmt_secondary_hold: |
1964 | LOADADDR(r5, hmt_thread_data) | 1972 | LOAD_REG_IMMEDIATE(r5, hmt_thread_data) |
1965 | clrldi r5,r5,4 | 1973 | clrldi r5,r5,4 |
1966 | li r7,0 | 1974 | li r7,0 |
1967 | mfspr r6,SPRN_PIR | 1975 | mfspr r6,SPRN_PIR |
@@ -1989,7 +1997,7 @@ __hmt_secondary_hold: | |||
1989 | 1997 | ||
1990 | #ifdef CONFIG_HMT | 1998 | #ifdef CONFIG_HMT |
1991 | _GLOBAL(hmt_start_secondary) | 1999 | _GLOBAL(hmt_start_secondary) |
1992 | LOADADDR(r4,__hmt_secondary_hold) | 2000 | LOAD_REG_IMMEDIATE(r4,__hmt_secondary_hold) |
1993 | clrldi r4,r4,4 | 2001 | clrldi r4,r4,4 |
1994 | mtspr SPRN_NIADORM, r4 | 2002 | mtspr SPRN_NIADORM, r4 |
1995 | mfspr r4, SPRN_MSRDORM | 2003 | mfspr r4, SPRN_MSRDORM |
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S index 1494e2f177f7..c16b4afab582 100644 --- a/arch/powerpc/kernel/idle_power4.S +++ b/arch/powerpc/kernel/idle_power4.S | |||
@@ -38,14 +38,14 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP) | |||
38 | /* We must dynamically check for the NAP feature as it | 38 | /* We must dynamically check for the NAP feature as it |
39 | * can be cleared by CPU init after the fixups are done | 39 | * can be cleared by CPU init after the fixups are done |
40 | */ | 40 | */ |
41 | LOADBASE(r3,cur_cpu_spec) | 41 | LOAD_REG_ADDRBASE(r3,cur_cpu_spec) |
42 | ld r4,OFF(cur_cpu_spec)(r3) | 42 | ld r4,ADDROFF(cur_cpu_spec)(r3) |
43 | ld r4,CPU_SPEC_FEATURES(r4) | 43 | ld r4,CPU_SPEC_FEATURES(r4) |
44 | andi. r0,r4,CPU_FTR_CAN_NAP | 44 | andi. r0,r4,CPU_FTR_CAN_NAP |
45 | beqlr | 45 | beqlr |
46 | /* Now check if user or arch enabled NAP mode */ | 46 | /* Now check if user or arch enabled NAP mode */ |
47 | LOADBASE(r3,powersave_nap) | 47 | LOAD_REG_ADDRBASE(r3,powersave_nap) |
48 | lwz r4,OFF(powersave_nap)(r3) | 48 | lwz r4,ADDROFF(powersave_nap)(r3) |
49 | cmpwi 0,r4,0 | 49 | cmpwi 0,r4,0 |
50 | beqlr | 50 | beqlr |
51 | 51 | ||
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 5651032d8706..d1fffce86df9 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -238,14 +238,10 @@ void do_IRQ(struct pt_regs *regs) | |||
238 | irq_exit(); | 238 | irq_exit(); |
239 | 239 | ||
240 | #ifdef CONFIG_PPC_ISERIES | 240 | #ifdef CONFIG_PPC_ISERIES |
241 | { | 241 | if (get_lppaca()->int_dword.fields.decr_int) { |
242 | struct paca_struct *lpaca = get_paca(); | 242 | get_lppaca()->int_dword.fields.decr_int = 0; |
243 | 243 | /* Signal a fake decrementer interrupt */ | |
244 | if (lpaca->lppaca.int_dword.fields.decr_int) { | 244 | timer_interrupt(regs); |
245 | lpaca->lppaca.int_dword.fields.decr_int = 0; | ||
246 | /* Signal a fake decrementer interrupt */ | ||
247 | timer_interrupt(regs); | ||
248 | } | ||
249 | } | 245 | } |
250 | #endif | 246 | #endif |
251 | } | 247 | } |
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 9dda16ccde78..1ae96a8ed7e2 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
@@ -55,15 +55,13 @@ static unsigned long get_purr(void) | |||
55 | { | 55 | { |
56 | unsigned long sum_purr = 0; | 56 | unsigned long sum_purr = 0; |
57 | int cpu; | 57 | int cpu; |
58 | struct paca_struct *lpaca; | ||
59 | 58 | ||
60 | for_each_cpu(cpu) { | 59 | for_each_cpu(cpu) { |
61 | lpaca = paca + cpu; | 60 | sum_purr += lppaca[cpu].emulated_time_base; |
62 | sum_purr += lpaca->lppaca.emulated_time_base; | ||
63 | 61 | ||
64 | #ifdef PURR_DEBUG | 62 | #ifdef PURR_DEBUG |
65 | printk(KERN_INFO "get_purr for cpu (%d) has value (%ld) \n", | 63 | printk(KERN_INFO "get_purr for cpu (%d) has value (%ld) \n", |
66 | cpu, lpaca->lppaca.emulated_time_base); | 64 | cpu, lppaca[cpu].emulated_time_base); |
67 | #endif | 65 | #endif |
68 | } | 66 | } |
69 | return sum_purr; | 67 | return sum_purr; |
@@ -79,12 +77,11 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
79 | unsigned long pool_id, lp_index; | 77 | unsigned long pool_id, lp_index; |
80 | int shared, entitled_capacity, max_entitled_capacity; | 78 | int shared, entitled_capacity, max_entitled_capacity; |
81 | int processors, max_processors; | 79 | int processors, max_processors; |
82 | struct paca_struct *lpaca = get_paca(); | ||
83 | unsigned long purr = get_purr(); | 80 | unsigned long purr = get_purr(); |
84 | 81 | ||
85 | seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS); | 82 | seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS); |
86 | 83 | ||
87 | shared = (int)(lpaca->lppaca_ptr->shared_proc); | 84 | shared = (int)(get_lppaca()->shared_proc); |
88 | seq_printf(m, "serial_number=%c%c%c%c%c%c%c\n", | 85 | seq_printf(m, "serial_number=%c%c%c%c%c%c%c\n", |
89 | e2a(xItExtVpdPanel.mfgID[2]), | 86 | e2a(xItExtVpdPanel.mfgID[2]), |
90 | e2a(xItExtVpdPanel.mfgID[3]), | 87 | e2a(xItExtVpdPanel.mfgID[3]), |
@@ -402,7 +399,7 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
402 | (h_resource >> 0 * 8) & 0xffff); | 399 | (h_resource >> 0 * 8) & 0xffff); |
403 | 400 | ||
404 | /* pool related entries are apropriate for shared configs */ | 401 | /* pool related entries are apropriate for shared configs */ |
405 | if (paca[0].lppaca.shared_proc) { | 402 | if (lppaca[0].shared_proc) { |
406 | 403 | ||
407 | h_pic(&pool_idle_time, &pool_procs); | 404 | h_pic(&pool_idle_time, &pool_procs); |
408 | 405 | ||
@@ -451,7 +448,7 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
451 | seq_printf(m, "partition_potential_processors=%d\n", | 448 | seq_printf(m, "partition_potential_processors=%d\n", |
452 | partition_potential_processors); | 449 | partition_potential_processors); |
453 | 450 | ||
454 | seq_printf(m, "shared_processor_mode=%d\n", paca[0].lppaca.shared_proc); | 451 | seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc); |
455 | 452 | ||
456 | return 0; | 453 | return 0; |
457 | } | 454 | } |
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 01d0d97a16e1..be982023409e 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
@@ -68,7 +68,7 @@ _GLOBAL(reloc_offset) | |||
68 | mflr r0 | 68 | mflr r0 |
69 | bl 1f | 69 | bl 1f |
70 | 1: mflr r3 | 70 | 1: mflr r3 |
71 | LOADADDR(r4,1b) | 71 | LOAD_REG_IMMEDIATE(r4,1b) |
72 | subf r3,r4,r3 | 72 | subf r3,r4,r3 |
73 | mtlr r0 | 73 | mtlr r0 |
74 | blr | 74 | blr |
@@ -80,7 +80,7 @@ _GLOBAL(add_reloc_offset) | |||
80 | mflr r0 | 80 | mflr r0 |
81 | bl 1f | 81 | bl 1f |
82 | 1: mflr r5 | 82 | 1: mflr r5 |
83 | LOADADDR(r4,1b) | 83 | LOAD_REG_IMMEDIATE(r4,1b) |
84 | subf r5,r4,r5 | 84 | subf r5,r4,r5 |
85 | add r3,r3,r5 | 85 | add r3,r3,r5 |
86 | mtlr r0 | 86 | mtlr r0 |
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index ae48a002f81a..2778cce058e2 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S | |||
@@ -39,7 +39,7 @@ _GLOBAL(reloc_offset) | |||
39 | mflr r0 | 39 | mflr r0 |
40 | bl 1f | 40 | bl 1f |
41 | 1: mflr r3 | 41 | 1: mflr r3 |
42 | LOADADDR(r4,1b) | 42 | LOAD_REG_IMMEDIATE(r4,1b) |
43 | subf r3,r4,r3 | 43 | subf r3,r4,r3 |
44 | mtlr r0 | 44 | mtlr r0 |
45 | blr | 45 | blr |
@@ -51,7 +51,7 @@ _GLOBAL(add_reloc_offset) | |||
51 | mflr r0 | 51 | mflr r0 |
52 | bl 1f | 52 | bl 1f |
53 | 1: mflr r5 | 53 | 1: mflr r5 |
54 | LOADADDR(r4,1b) | 54 | LOAD_REG_IMMEDIATE(r4,1b) |
55 | subf r5,r4,r5 | 55 | subf r5,r4,r5 |
56 | add r3,r3,r5 | 56 | add r3,r3,r5 |
57 | mtlr r0 | 57 | mtlr r0 |
@@ -498,15 +498,15 @@ _GLOBAL(identify_cpu) | |||
498 | */ | 498 | */ |
499 | _GLOBAL(do_cpu_ftr_fixups) | 499 | _GLOBAL(do_cpu_ftr_fixups) |
500 | /* Get CPU 0 features */ | 500 | /* Get CPU 0 features */ |
501 | LOADADDR(r6,cur_cpu_spec) | 501 | LOAD_REG_IMMEDIATE(r6,cur_cpu_spec) |
502 | sub r6,r6,r3 | 502 | sub r6,r6,r3 |
503 | ld r4,0(r6) | 503 | ld r4,0(r6) |
504 | sub r4,r4,r3 | 504 | sub r4,r4,r3 |
505 | ld r4,CPU_SPEC_FEATURES(r4) | 505 | ld r4,CPU_SPEC_FEATURES(r4) |
506 | /* Get the fixup table */ | 506 | /* Get the fixup table */ |
507 | LOADADDR(r6,__start___ftr_fixup) | 507 | LOAD_REG_IMMEDIATE(r6,__start___ftr_fixup) |
508 | sub r6,r6,r3 | 508 | sub r6,r6,r3 |
509 | LOADADDR(r7,__stop___ftr_fixup) | 509 | LOAD_REG_IMMEDIATE(r7,__stop___ftr_fixup) |
510 | sub r7,r7,r3 | 510 | sub r7,r7,r3 |
511 | /* Do the fixup */ | 511 | /* Do the fixup */ |
512 | 1: cmpld r6,r7 | 512 | 1: cmpld r6,r7 |
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index 999bdd816769..5d1b708086bd 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c | |||
@@ -25,6 +25,28 @@ | |||
25 | * field correctly */ | 25 | * field correctly */ |
26 | extern unsigned long __toc_start; | 26 | extern unsigned long __toc_start; |
27 | 27 | ||
28 | /* | ||
29 | * iSeries structure which the hypervisor knows about - this structure | ||
30 | * should not cross a page boundary. The vpa_init/register_vpa call | ||
31 | * is now known to fail if the lppaca structure crosses a page | ||
32 | * boundary. The lppaca is also used on POWER5 pSeries boxes. The | ||
33 | * lppaca is 640 bytes long, and cannot readily change since the | ||
34 | * hypervisor knows its layout, so a 1kB alignment will suffice to | ||
35 | * ensure that it doesn't cross a page boundary. | ||
36 | */ | ||
37 | struct lppaca lppaca[] = { | ||
38 | [0 ... (NR_CPUS-1)] = { | ||
39 | .desc = 0xd397d781, /* "LpPa" */ | ||
40 | .size = sizeof(struct lppaca), | ||
41 | .dyn_proc_status = 2, | ||
42 | .decr_val = 0x00ff0000, | ||
43 | .fpregs_in_use = 1, | ||
44 | .end_of_quantum = 0xfffffffffffffffful, | ||
45 | .slb_count = 64, | ||
46 | .vmxregs_in_use = 0, | ||
47 | }, | ||
48 | }; | ||
49 | |||
28 | /* The Paca is an array with one entry per processor. Each contains an | 50 | /* The Paca is an array with one entry per processor. Each contains an |
29 | * lppaca, which contains the information shared between the | 51 | * lppaca, which contains the information shared between the |
30 | * hypervisor and Linux. | 52 | * hypervisor and Linux. |
@@ -35,27 +57,17 @@ extern unsigned long __toc_start; | |||
35 | * processor (not thread). | 57 | * processor (not thread). |
36 | */ | 58 | */ |
37 | #define PACA_INIT_COMMON(number, start, asrr, asrv) \ | 59 | #define PACA_INIT_COMMON(number, start, asrr, asrv) \ |
60 | .lppaca_ptr = &lppaca[number], \ | ||
38 | .lock_token = 0x8000, \ | 61 | .lock_token = 0x8000, \ |
39 | .paca_index = (number), /* Paca Index */ \ | 62 | .paca_index = (number), /* Paca Index */ \ |
40 | .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \ | 63 | .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \ |
41 | .stab_real = (asrr), /* Real pointer to segment table */ \ | 64 | .stab_real = (asrr), /* Real pointer to segment table */ \ |
42 | .stab_addr = (asrv), /* Virt pointer to segment table */ \ | 65 | .stab_addr = (asrv), /* Virt pointer to segment table */ \ |
43 | .cpu_start = (start), /* Processor start */ \ | 66 | .cpu_start = (start), /* Processor start */ \ |
44 | .hw_cpu_id = 0xffff, \ | 67 | .hw_cpu_id = 0xffff, |
45 | .lppaca = { \ | ||
46 | .desc = 0xd397d781, /* "LpPa" */ \ | ||
47 | .size = sizeof(struct lppaca), \ | ||
48 | .dyn_proc_status = 2, \ | ||
49 | .decr_val = 0x00ff0000, \ | ||
50 | .fpregs_in_use = 1, \ | ||
51 | .end_of_quantum = 0xfffffffffffffffful, \ | ||
52 | .slb_count = 64, \ | ||
53 | .vmxregs_in_use = 0, \ | ||
54 | }, \ | ||
55 | 68 | ||
56 | #ifdef CONFIG_PPC_ISERIES | 69 | #ifdef CONFIG_PPC_ISERIES |
57 | #define PACA_INIT_ISERIES(number) \ | 70 | #define PACA_INIT_ISERIES(number) \ |
58 | .lppaca_ptr = &paca[number].lppaca, \ | ||
59 | .reg_save_ptr = &iseries_reg_save[number], | 71 | .reg_save_ptr = &iseries_reg_save[number], |
60 | 72 | ||
61 | #define PACA_INIT(number) \ | 73 | #define PACA_INIT(number) \ |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 16d9a904f3cb..d9a459c144d8 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -230,8 +230,7 @@ EXPORT_SYMBOL(__down_interruptible); | |||
230 | EXPORT_SYMBOL(cpm_install_handler); | 230 | EXPORT_SYMBOL(cpm_install_handler); |
231 | EXPORT_SYMBOL(cpm_free_handler); | 231 | EXPORT_SYMBOL(cpm_free_handler); |
232 | #endif /* CONFIG_8xx */ | 232 | #endif /* CONFIG_8xx */ |
233 | #if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx) ||\ | 233 | #if defined(CONFIG_8xx) || defined(CONFIG_40x) |
234 | defined(CONFIG_83xx) | ||
235 | EXPORT_SYMBOL(__res); | 234 | EXPORT_SYMBOL(__res); |
236 | #endif | 235 | #endif |
237 | 236 | ||
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 02e2115323e4..d50c8df0183e 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -1627,6 +1627,11 @@ static void of_node_release(struct kref *kref) | |||
1627 | kfree(prop->value); | 1627 | kfree(prop->value); |
1628 | kfree(prop); | 1628 | kfree(prop); |
1629 | prop = next; | 1629 | prop = next; |
1630 | |||
1631 | if (!prop) { | ||
1632 | prop = node->deadprops; | ||
1633 | node->deadprops = NULL; | ||
1634 | } | ||
1630 | } | 1635 | } |
1631 | kfree(node->intrs); | 1636 | kfree(node->intrs); |
1632 | kfree(node->full_name); | 1637 | kfree(node->full_name); |
@@ -1774,22 +1779,32 @@ static int __init prom_reconfig_setup(void) | |||
1774 | __initcall(prom_reconfig_setup); | 1779 | __initcall(prom_reconfig_setup); |
1775 | #endif | 1780 | #endif |
1776 | 1781 | ||
1777 | /* | 1782 | struct property *of_find_property(struct device_node *np, const char *name, |
1778 | * Find a property with a given name for a given node | 1783 | int *lenp) |
1779 | * and return the value. | ||
1780 | */ | ||
1781 | unsigned char *get_property(struct device_node *np, const char *name, | ||
1782 | int *lenp) | ||
1783 | { | 1784 | { |
1784 | struct property *pp; | 1785 | struct property *pp; |
1785 | 1786 | ||
1787 | read_lock(&devtree_lock); | ||
1786 | for (pp = np->properties; pp != 0; pp = pp->next) | 1788 | for (pp = np->properties; pp != 0; pp = pp->next) |
1787 | if (strcmp(pp->name, name) == 0) { | 1789 | if (strcmp(pp->name, name) == 0) { |
1788 | if (lenp != 0) | 1790 | if (lenp != 0) |
1789 | *lenp = pp->length; | 1791 | *lenp = pp->length; |
1790 | return pp->value; | 1792 | break; |
1791 | } | 1793 | } |
1792 | return NULL; | 1794 | read_unlock(&devtree_lock); |
1795 | |||
1796 | return pp; | ||
1797 | } | ||
1798 | |||
1799 | /* | ||
1800 | * Find a property with a given name for a given node | ||
1801 | * and return the value. | ||
1802 | */ | ||
1803 | unsigned char *get_property(struct device_node *np, const char *name, | ||
1804 | int *lenp) | ||
1805 | { | ||
1806 | struct property *pp = of_find_property(np,name,lenp); | ||
1807 | return pp ? pp->value : NULL; | ||
1793 | } | 1808 | } |
1794 | EXPORT_SYMBOL(get_property); | 1809 | EXPORT_SYMBOL(get_property); |
1795 | 1810 | ||
@@ -1823,4 +1838,82 @@ int prom_add_property(struct device_node* np, struct property* prop) | |||
1823 | return 0; | 1838 | return 0; |
1824 | } | 1839 | } |
1825 | 1840 | ||
1841 | /* | ||
1842 | * Remove a property from a node. Note that we don't actually | ||
1843 | * remove it, since we have given out who-knows-how-many pointers | ||
1844 | * to the data using get-property. Instead we just move the property | ||
1845 | * to the "dead properties" list, so it won't be found any more. | ||
1846 | */ | ||
1847 | int prom_remove_property(struct device_node *np, struct property *prop) | ||
1848 | { | ||
1849 | struct property **next; | ||
1850 | int found = 0; | ||
1826 | 1851 | ||
1852 | write_lock(&devtree_lock); | ||
1853 | next = &np->properties; | ||
1854 | while (*next) { | ||
1855 | if (*next == prop) { | ||
1856 | /* found the node */ | ||
1857 | *next = prop->next; | ||
1858 | prop->next = np->deadprops; | ||
1859 | np->deadprops = prop; | ||
1860 | found = 1; | ||
1861 | break; | ||
1862 | } | ||
1863 | next = &(*next)->next; | ||
1864 | } | ||
1865 | write_unlock(&devtree_lock); | ||
1866 | |||
1867 | if (!found) | ||
1868 | return -ENODEV; | ||
1869 | |||
1870 | #ifdef CONFIG_PROC_DEVICETREE | ||
1871 | /* try to remove the proc node as well */ | ||
1872 | if (np->pde) | ||
1873 | proc_device_tree_remove_prop(np->pde, prop); | ||
1874 | #endif /* CONFIG_PROC_DEVICETREE */ | ||
1875 | |||
1876 | return 0; | ||
1877 | } | ||
1878 | |||
1879 | /* | ||
1880 | * Update a property in a node. Note that we don't actually | ||
1881 | * remove it, since we have given out who-knows-how-many pointers | ||
1882 | * to the data using get-property. Instead we just move the property | ||
1883 | * to the "dead properties" list, and add the new property to the | ||
1884 | * property list | ||
1885 | */ | ||
1886 | int prom_update_property(struct device_node *np, | ||
1887 | struct property *newprop, | ||
1888 | struct property *oldprop) | ||
1889 | { | ||
1890 | struct property **next; | ||
1891 | int found = 0; | ||
1892 | |||
1893 | write_lock(&devtree_lock); | ||
1894 | next = &np->properties; | ||
1895 | while (*next) { | ||
1896 | if (*next == oldprop) { | ||
1897 | /* found the node */ | ||
1898 | newprop->next = oldprop->next; | ||
1899 | *next = newprop; | ||
1900 | oldprop->next = np->deadprops; | ||
1901 | np->deadprops = oldprop; | ||
1902 | found = 1; | ||
1903 | break; | ||
1904 | } | ||
1905 | next = &(*next)->next; | ||
1906 | } | ||
1907 | write_unlock(&devtree_lock); | ||
1908 | |||
1909 | if (!found) | ||
1910 | return -ENODEV; | ||
1911 | |||
1912 | #ifdef CONFIG_PROC_DEVICETREE | ||
1913 | /* try to add to proc as well if it was initialized */ | ||
1914 | if (np->pde) | ||
1915 | proc_device_tree_update_prop(np->pde, newprop, oldprop); | ||
1916 | #endif /* CONFIG_PROC_DEVICETREE */ | ||
1917 | |||
1918 | return 0; | ||
1919 | } | ||
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 309ae1d5fa77..a8099c806150 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c | |||
@@ -113,7 +113,8 @@ static unsigned int of_bus_default_get_flags(u32 *addr) | |||
113 | 113 | ||
114 | static int of_bus_pci_match(struct device_node *np) | 114 | static int of_bus_pci_match(struct device_node *np) |
115 | { | 115 | { |
116 | return !strcmp(np->type, "pci"); | 116 | /* "vci" is for the /chaos bridge on 1st-gen PCI powermacs */ |
117 | return !strcmp(np->type, "pci") || !strcmp(np->type, "vci"); | ||
117 | } | 118 | } |
118 | 119 | ||
119 | static void of_bus_pci_count_cells(struct device_node *np, | 120 | static void of_bus_pci_count_cells(struct device_node *np, |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 4b9cfe4637b1..7fe4a5c944c9 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -36,6 +36,11 @@ struct rtas_t rtas = { | |||
36 | .lock = SPIN_LOCK_UNLOCKED | 36 | .lock = SPIN_LOCK_UNLOCKED |
37 | }; | 37 | }; |
38 | 38 | ||
39 | struct rtas_suspend_me_data { | ||
40 | long waiting; | ||
41 | struct rtas_args *args; | ||
42 | }; | ||
43 | |||
39 | EXPORT_SYMBOL(rtas); | 44 | EXPORT_SYMBOL(rtas); |
40 | 45 | ||
41 | DEFINE_SPINLOCK(rtas_data_buf_lock); | 46 | DEFINE_SPINLOCK(rtas_data_buf_lock); |
@@ -556,6 +561,80 @@ void rtas_os_term(char *str) | |||
556 | } while (status == RTAS_BUSY); | 561 | } while (status == RTAS_BUSY); |
557 | } | 562 | } |
558 | 563 | ||
564 | static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; | ||
565 | #ifdef CONFIG_PPC_PSERIES | ||
566 | static void rtas_percpu_suspend_me(void *info) | ||
567 | { | ||
568 | long rc; | ||
569 | long flags; | ||
570 | struct rtas_suspend_me_data *data = | ||
571 | (struct rtas_suspend_me_data *)info; | ||
572 | |||
573 | /* | ||
574 | * We use "waiting" to indicate our state. As long | ||
575 | * as it is >0, we are still trying to all join up. | ||
576 | * If it goes to 0, we have successfully joined up and | ||
577 | * one thread got H_Continue. If any error happens, | ||
578 | * we set it to <0. | ||
579 | */ | ||
580 | local_irq_save(flags); | ||
581 | do { | ||
582 | rc = plpar_hcall_norets(H_JOIN); | ||
583 | smp_rmb(); | ||
584 | } while (rc == H_Success && data->waiting > 0); | ||
585 | if (rc == H_Success) | ||
586 | goto out; | ||
587 | |||
588 | if (rc == H_Continue) { | ||
589 | data->waiting = 0; | ||
590 | rtas_call(ibm_suspend_me_token, 0, 1, | ||
591 | data->args->args); | ||
592 | } else { | ||
593 | data->waiting = -EBUSY; | ||
594 | printk(KERN_ERR "Error on H_Join hypervisor call\n"); | ||
595 | } | ||
596 | |||
597 | out: | ||
598 | /* before we restore interrupts, make sure we don't | ||
599 | * generate a spurious soft lockup errors | ||
600 | */ | ||
601 | touch_softlockup_watchdog(); | ||
602 | local_irq_restore(flags); | ||
603 | return; | ||
604 | } | ||
605 | |||
606 | static int rtas_ibm_suspend_me(struct rtas_args *args) | ||
607 | { | ||
608 | int i; | ||
609 | |||
610 | struct rtas_suspend_me_data data; | ||
611 | |||
612 | data.waiting = 1; | ||
613 | data.args = args; | ||
614 | |||
615 | /* Call function on all CPUs. One of us will make the | ||
616 | * rtas call | ||
617 | */ | ||
618 | if (on_each_cpu(rtas_percpu_suspend_me, &data, 1, 0)) | ||
619 | data.waiting = -EINVAL; | ||
620 | |||
621 | if (data.waiting != 0) | ||
622 | printk(KERN_ERR "Error doing global join\n"); | ||
623 | |||
624 | /* Prod each CPU. This won't hurt, and will wake | ||
625 | * anyone we successfully put to sleep with H_Join | ||
626 | */ | ||
627 | for_each_cpu(i) | ||
628 | plpar_hcall_norets(H_PROD, i); | ||
629 | |||
630 | return data.waiting; | ||
631 | } | ||
632 | #else /* CONFIG_PPC_PSERIES */ | ||
633 | static int rtas_ibm_suspend_me(struct rtas_args *args) | ||
634 | { | ||
635 | return -ENOSYS; | ||
636 | } | ||
637 | #endif | ||
559 | 638 | ||
560 | asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | 639 | asmlinkage int ppc_rtas(struct rtas_args __user *uargs) |
561 | { | 640 | { |
@@ -563,6 +642,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
563 | unsigned long flags; | 642 | unsigned long flags; |
564 | char *buff_copy, *errbuf = NULL; | 643 | char *buff_copy, *errbuf = NULL; |
565 | int nargs; | 644 | int nargs; |
645 | int rc; | ||
566 | 646 | ||
567 | if (!capable(CAP_SYS_ADMIN)) | 647 | if (!capable(CAP_SYS_ADMIN)) |
568 | return -EPERM; | 648 | return -EPERM; |
@@ -581,6 +661,17 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
581 | nargs * sizeof(rtas_arg_t)) != 0) | 661 | nargs * sizeof(rtas_arg_t)) != 0) |
582 | return -EFAULT; | 662 | return -EFAULT; |
583 | 663 | ||
664 | if (args.token == RTAS_UNKNOWN_SERVICE) | ||
665 | return -EINVAL; | ||
666 | |||
667 | /* Need to handle ibm,suspend_me call specially */ | ||
668 | if (args.token == ibm_suspend_me_token) { | ||
669 | rc = rtas_ibm_suspend_me(&args); | ||
670 | if (rc) | ||
671 | return rc; | ||
672 | goto copy_return; | ||
673 | } | ||
674 | |||
584 | buff_copy = get_errorlog_buffer(); | 675 | buff_copy = get_errorlog_buffer(); |
585 | 676 | ||
586 | spin_lock_irqsave(&rtas.lock, flags); | 677 | spin_lock_irqsave(&rtas.lock, flags); |
@@ -604,6 +695,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
604 | kfree(buff_copy); | 695 | kfree(buff_copy); |
605 | } | 696 | } |
606 | 697 | ||
698 | copy_return: | ||
607 | /* Copy out args. */ | 699 | /* Copy out args. */ |
608 | if (copy_to_user(uargs->args + nargs, | 700 | if (copy_to_user(uargs->args + nargs, |
609 | args.args + nargs, | 701 | args.args + nargs, |
@@ -675,8 +767,10 @@ void __init rtas_initialize(void) | |||
675 | * the stop-self token if any | 767 | * the stop-self token if any |
676 | */ | 768 | */ |
677 | #ifdef CONFIG_PPC64 | 769 | #ifdef CONFIG_PPC64 |
678 | if (_machine == PLATFORM_PSERIES_LPAR) | 770 | if (_machine == PLATFORM_PSERIES_LPAR) { |
679 | rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); | 771 | rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); |
772 | ibm_suspend_me_token = rtas_token("ibm,suspend-me"); | ||
773 | } | ||
680 | #endif | 774 | #endif |
681 | rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region); | 775 | rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region); |
682 | 776 | ||
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index d5c52fae023a..be12041c0fc5 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
@@ -100,7 +100,8 @@ void machine_shutdown(void) | |||
100 | void machine_restart(char *cmd) | 100 | void machine_restart(char *cmd) |
101 | { | 101 | { |
102 | machine_shutdown(); | 102 | machine_shutdown(); |
103 | ppc_md.restart(cmd); | 103 | if (ppc_md.restart) |
104 | ppc_md.restart(cmd); | ||
104 | #ifdef CONFIG_SMP | 105 | #ifdef CONFIG_SMP |
105 | smp_send_stop(); | 106 | smp_send_stop(); |
106 | #endif | 107 | #endif |
@@ -112,7 +113,8 @@ void machine_restart(char *cmd) | |||
112 | void machine_power_off(void) | 113 | void machine_power_off(void) |
113 | { | 114 | { |
114 | machine_shutdown(); | 115 | machine_shutdown(); |
115 | ppc_md.power_off(); | 116 | if (ppc_md.power_off) |
117 | ppc_md.power_off(); | ||
116 | #ifdef CONFIG_SMP | 118 | #ifdef CONFIG_SMP |
117 | smp_send_stop(); | 119 | smp_send_stop(); |
118 | #endif | 120 | #endif |
@@ -129,7 +131,8 @@ EXPORT_SYMBOL_GPL(pm_power_off); | |||
129 | void machine_halt(void) | 131 | void machine_halt(void) |
130 | { | 132 | { |
131 | machine_shutdown(); | 133 | machine_shutdown(); |
132 | ppc_md.halt(); | 134 | if (ppc_md.halt) |
135 | ppc_md.halt(); | ||
133 | #ifdef CONFIG_SMP | 136 | #ifdef CONFIG_SMP |
134 | smp_send_stop(); | 137 | smp_send_stop(); |
135 | #endif | 138 | #endif |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 56f50e91bddb..c4a294d657b9 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -431,7 +431,7 @@ void timer_interrupt(struct pt_regs * regs) | |||
431 | profile_tick(CPU_PROFILING, regs); | 431 | profile_tick(CPU_PROFILING, regs); |
432 | 432 | ||
433 | #ifdef CONFIG_PPC_ISERIES | 433 | #ifdef CONFIG_PPC_ISERIES |
434 | get_paca()->lppaca.int_dword.fields.decr_int = 0; | 434 | get_lppaca()->int_dword.fields.decr_int = 0; |
435 | #endif | 435 | #endif |
436 | 436 | ||
437 | while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu))) | 437 | while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu))) |
diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c index 35bd03c41dd1..8362fa272ca5 100644 --- a/arch/powerpc/lib/locks.c +++ b/arch/powerpc/lib/locks.c | |||
@@ -28,15 +28,13 @@ | |||
28 | void __spin_yield(raw_spinlock_t *lock) | 28 | void __spin_yield(raw_spinlock_t *lock) |
29 | { | 29 | { |
30 | unsigned int lock_value, holder_cpu, yield_count; | 30 | unsigned int lock_value, holder_cpu, yield_count; |
31 | struct paca_struct *holder_paca; | ||
32 | 31 | ||
33 | lock_value = lock->slock; | 32 | lock_value = lock->slock; |
34 | if (lock_value == 0) | 33 | if (lock_value == 0) |
35 | return; | 34 | return; |
36 | holder_cpu = lock_value & 0xffff; | 35 | holder_cpu = lock_value & 0xffff; |
37 | BUG_ON(holder_cpu >= NR_CPUS); | 36 | BUG_ON(holder_cpu >= NR_CPUS); |
38 | holder_paca = &paca[holder_cpu]; | 37 | yield_count = lppaca[holder_cpu].yield_count; |
39 | yield_count = holder_paca->lppaca.yield_count; | ||
40 | if ((yield_count & 1) == 0) | 38 | if ((yield_count & 1) == 0) |
41 | return; /* virtual cpu is currently running */ | 39 | return; /* virtual cpu is currently running */ |
42 | rmb(); | 40 | rmb(); |
@@ -60,15 +58,13 @@ void __rw_yield(raw_rwlock_t *rw) | |||
60 | { | 58 | { |
61 | int lock_value; | 59 | int lock_value; |
62 | unsigned int holder_cpu, yield_count; | 60 | unsigned int holder_cpu, yield_count; |
63 | struct paca_struct *holder_paca; | ||
64 | 61 | ||
65 | lock_value = rw->lock; | 62 | lock_value = rw->lock; |
66 | if (lock_value >= 0) | 63 | if (lock_value >= 0) |
67 | return; /* no write lock at present */ | 64 | return; /* no write lock at present */ |
68 | holder_cpu = lock_value & 0xffff; | 65 | holder_cpu = lock_value & 0xffff; |
69 | BUG_ON(holder_cpu >= NR_CPUS); | 66 | BUG_ON(holder_cpu >= NR_CPUS); |
70 | holder_paca = &paca[holder_cpu]; | 67 | yield_count = lppaca[holder_cpu].yield_count; |
71 | yield_count = holder_paca->lppaca.yield_count; | ||
72 | if ((yield_count & 1) == 0) | 68 | if ((yield_count & 1) == 0) |
73 | return; /* virtual cpu is currently running */ | 69 | return; /* virtual cpu is currently running */ |
74 | rmb(); | 70 | rmb(); |
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index 71615eb70b2b..cc2535be3a73 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c | |||
@@ -140,19 +140,19 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) | |||
140 | 140 | ||
141 | switch (cur_cpu_spec->oprofile_type) { | 141 | switch (cur_cpu_spec->oprofile_type) { |
142 | #ifdef CONFIG_PPC64 | 142 | #ifdef CONFIG_PPC64 |
143 | case RS64: | 143 | case PPC_OPROFILE_RS64: |
144 | model = &op_model_rs64; | 144 | model = &op_model_rs64; |
145 | break; | 145 | break; |
146 | case POWER4: | 146 | case PPC_OPROFILE_POWER4: |
147 | model = &op_model_power4; | 147 | model = &op_model_power4; |
148 | break; | 148 | break; |
149 | #else | 149 | #else |
150 | case G4: | 150 | case PPC_OPROFILE_G4: |
151 | model = &op_model_7450; | 151 | model = &op_model_7450; |
152 | break; | 152 | break; |
153 | #endif | 153 | #endif |
154 | #ifdef CONFIG_FSL_BOOKE | 154 | #ifdef CONFIG_FSL_BOOKE |
155 | case BOOKE: | 155 | case PPC_OPROFILE_BOOKE: |
156 | model = &op_model_fsl_booke; | 156 | model = &op_model_fsl_booke; |
157 | break; | 157 | break; |
158 | #endif | 158 | #endif |
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index b20812d460e6..7675e675dce1 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig | |||
@@ -7,6 +7,7 @@ choice | |||
7 | 7 | ||
8 | config MPC834x_SYS | 8 | config MPC834x_SYS |
9 | bool "Freescale MPC834x SYS" | 9 | bool "Freescale MPC834x SYS" |
10 | select DEFAULT_UIMAGE | ||
10 | help | 11 | help |
11 | This option enables support for the MPC 834x SYS evaluation board. | 12 | This option enables support for the MPC 834x SYS evaluation board. |
12 | 13 | ||
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c new file mode 100644 index 000000000000..2098dd05a773 --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c | |||
@@ -0,0 +1,243 @@ | |||
1 | /* | ||
2 | * arch/powerpc/platforms/83xx/mpc834x_sys.c | ||
3 | * | ||
4 | * MPC834x SYS board specific routines | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/stddef.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/reboot.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/kdev_t.h> | ||
22 | #include <linux/major.h> | ||
23 | #include <linux/console.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/seq_file.h> | ||
26 | #include <linux/root_dev.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/fsl_devices.h> | ||
29 | |||
30 | #include <asm/system.h> | ||
31 | #include <asm/pgtable.h> | ||
32 | #include <asm/page.h> | ||
33 | #include <asm/atomic.h> | ||
34 | #include <asm/time.h> | ||
35 | #include <asm/io.h> | ||
36 | #include <asm/machdep.h> | ||
37 | #include <asm/ipic.h> | ||
38 | #include <asm/bootinfo.h> | ||
39 | #include <asm/pci-bridge.h> | ||
40 | #include <asm/mpc83xx.h> | ||
41 | #include <asm/irq.h> | ||
42 | #include <mm/mmu_decl.h> | ||
43 | #include <asm/prom.h> | ||
44 | #include <asm/udbg.h> | ||
45 | #include <sysdev/fsl_soc.h> | ||
46 | |||
47 | #include "mpc83xx.h" | ||
48 | |||
49 | #ifndef CONFIG_PCI | ||
50 | unsigned long isa_io_base = 0; | ||
51 | unsigned long isa_mem_base = 0; | ||
52 | #endif | ||
53 | |||
54 | #ifdef CONFIG_PCI | ||
55 | extern int mpc83xx_pci2_busno; | ||
56 | |||
57 | static int | ||
58 | mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
59 | { | ||
60 | static char pci_irq_table[][4] = | ||
61 | /* | ||
62 | * PCI IDSEL/INTPIN->INTLINE | ||
63 | * A B C D | ||
64 | */ | ||
65 | { | ||
66 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */ | ||
67 | {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */ | ||
68 | {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x13 */ | ||
69 | {0, 0, 0, 0}, | ||
70 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x15 */ | ||
71 | {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x16 */ | ||
72 | {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x17 */ | ||
73 | {PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x18 */ | ||
74 | {0, 0, 0, 0}, /* idsel 0x19 */ | ||
75 | {0, 0, 0, 0}, /* idsel 0x20 */ | ||
76 | }; | ||
77 | |||
78 | const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4; | ||
79 | return PCI_IRQ_TABLE_LOOKUP; | ||
80 | } | ||
81 | |||
82 | static int | ||
83 | mpc83xx_exclude_device(u_char bus, u_char devfn) | ||
84 | { | ||
85 | if (bus == 0 && PCI_SLOT(devfn) == 0) | ||
86 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
87 | if (mpc83xx_pci2_busno) | ||
88 | if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0) | ||
89 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
90 | return PCIBIOS_SUCCESSFUL; | ||
91 | } | ||
92 | #endif /* CONFIG_PCI */ | ||
93 | |||
94 | /* ************************************************************************ | ||
95 | * | ||
96 | * Setup the architecture | ||
97 | * | ||
98 | */ | ||
99 | static void __init | ||
100 | mpc834x_sys_setup_arch(void) | ||
101 | { | ||
102 | struct device_node *np; | ||
103 | |||
104 | if (ppc_md.progress) | ||
105 | ppc_md.progress("mpc834x_sys_setup_arch()", 0); | ||
106 | |||
107 | np = of_find_node_by_type(NULL, "cpu"); | ||
108 | if (np != 0) { | ||
109 | unsigned int *fp = (int *) get_property(np, "clock-frequency", NULL); | ||
110 | if (fp != 0) | ||
111 | loops_per_jiffy = *fp / HZ; | ||
112 | else | ||
113 | loops_per_jiffy = 50000000 / HZ; | ||
114 | of_node_put(np); | ||
115 | } | ||
116 | |||
117 | #ifdef CONFIG_PCI | ||
118 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | ||
119 | add_bridge(np); | ||
120 | |||
121 | ppc_md.pci_swizzle = common_swizzle; | ||
122 | ppc_md.pci_map_irq = mpc83xx_map_irq; | ||
123 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | ||
124 | #endif | ||
125 | |||
126 | #ifdef CONFIG_ROOT_NFS | ||
127 | ROOT_DEV = Root_NFS; | ||
128 | #else | ||
129 | ROOT_DEV = Root_HDA1; | ||
130 | #endif | ||
131 | } | ||
132 | |||
133 | void __init | ||
134 | mpc834x_sys_init_IRQ(void) | ||
135 | { | ||
136 | u8 senses[8] = { | ||
137 | 0, /* EXT 0 */ | ||
138 | IRQ_SENSE_LEVEL, /* EXT 1 */ | ||
139 | IRQ_SENSE_LEVEL, /* EXT 2 */ | ||
140 | 0, /* EXT 3 */ | ||
141 | #ifdef CONFIG_PCI | ||
142 | IRQ_SENSE_LEVEL, /* EXT 4 */ | ||
143 | IRQ_SENSE_LEVEL, /* EXT 5 */ | ||
144 | IRQ_SENSE_LEVEL, /* EXT 6 */ | ||
145 | IRQ_SENSE_LEVEL, /* EXT 7 */ | ||
146 | #else | ||
147 | 0, /* EXT 4 */ | ||
148 | 0, /* EXT 5 */ | ||
149 | 0, /* EXT 6 */ | ||
150 | 0, /* EXT 7 */ | ||
151 | #endif | ||
152 | }; | ||
153 | |||
154 | ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8); | ||
155 | |||
156 | /* Initialize the default interrupt mapping priorities, | ||
157 | * in case the boot rom changed something on us. | ||
158 | */ | ||
159 | ipic_set_default_priority(); | ||
160 | } | ||
161 | |||
162 | #if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374) | ||
163 | extern ulong ds1374_get_rtc_time(void); | ||
164 | extern int ds1374_set_rtc_time(ulong); | ||
165 | |||
166 | static int __init | ||
167 | mpc834x_rtc_hookup(void) | ||
168 | { | ||
169 | struct timespec tv; | ||
170 | |||
171 | ppc_md.get_rtc_time = ds1374_get_rtc_time; | ||
172 | ppc_md.set_rtc_time = ds1374_set_rtc_time; | ||
173 | |||
174 | tv.tv_nsec = 0; | ||
175 | tv.tv_sec = (ppc_md.get_rtc_time)(); | ||
176 | do_settimeofday(&tv); | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | late_initcall(mpc834x_rtc_hookup); | ||
181 | #endif | ||
182 | |||
183 | static void | ||
184 | mpc83xx_restart(char *cmd) | ||
185 | { | ||
186 | #define RST_OFFSET 0x00000900 | ||
187 | #define RST_PROT_REG 0x00000018 | ||
188 | #define RST_CTRL_REG 0x0000001c | ||
189 | __be32 __iomem *reg; | ||
190 | |||
191 | // map reset register space | ||
192 | reg = ioremap(get_immrbase() + 0x900, 0xff); | ||
193 | |||
194 | local_irq_disable(); | ||
195 | |||
196 | /* enable software reset "RSTE" */ | ||
197 | out_be32(reg + (RST_PROT_REG >> 2), 0x52535445); | ||
198 | |||
199 | /* set software hard reset */ | ||
200 | out_be32(reg + (RST_CTRL_REG >> 2), 0x52535445); | ||
201 | for(;;); | ||
202 | } | ||
203 | |||
204 | static long __init | ||
205 | mpc83xx_time_init(void) | ||
206 | { | ||
207 | #define SPCR_OFFSET 0x00000110 | ||
208 | #define SPCR_TBEN 0x00400000 | ||
209 | __be32 __iomem *spcr = ioremap(get_immrbase() + SPCR_OFFSET, 4); | ||
210 | __be32 tmp; | ||
211 | |||
212 | tmp = in_be32(spcr); | ||
213 | out_be32(spcr, tmp|SPCR_TBEN); | ||
214 | |||
215 | iounmap(spcr); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | void __init | ||
220 | platform_init(void) | ||
221 | { | ||
222 | /* setup the PowerPC module struct */ | ||
223 | ppc_md.setup_arch = mpc834x_sys_setup_arch; | ||
224 | |||
225 | ppc_md.init_IRQ = mpc834x_sys_init_IRQ; | ||
226 | ppc_md.get_irq = ipic_get_irq; | ||
227 | |||
228 | ppc_md.restart = mpc83xx_restart; | ||
229 | |||
230 | ppc_md.time_init = mpc83xx_time_init; | ||
231 | ppc_md.set_rtc_time = NULL; | ||
232 | ppc_md.get_rtc_time = NULL; | ||
233 | ppc_md.calibrate_decr = generic_calibrate_decr; | ||
234 | |||
235 | ppc_md.progress = udbg_progress; | ||
236 | |||
237 | if (ppc_md.progress) | ||
238 | ppc_md.progress("mpc834x_sys_init(): exit", 0); | ||
239 | |||
240 | return; | ||
241 | } | ||
242 | |||
243 | |||
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.h b/arch/powerpc/platforms/83xx/mpc834x_sys.h new file mode 100644 index 000000000000..e4ca39f6a862 --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * arch/powerppc/platforms/83xx/mpc834x_sys.h | ||
3 | * | ||
4 | * MPC834X SYS common board definitions | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #ifndef __MACH_MPC83XX_SYS_H__ | ||
16 | #define __MACH_MPC83XX_SYS_H__ | ||
17 | |||
18 | #define PIRQA MPC83xx_IRQ_EXT4 | ||
19 | #define PIRQB MPC83xx_IRQ_EXT5 | ||
20 | #define PIRQC MPC83xx_IRQ_EXT6 | ||
21 | #define PIRQD MPC83xx_IRQ_EXT7 | ||
22 | |||
23 | #endif /* __MACH_MPC83XX_SYS_H__ */ | ||
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h new file mode 100644 index 000000000000..ce9e66abef24 --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc83xx.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef __MPC83XX_H__ | ||
2 | #define __MPC83XX_H__ | ||
3 | |||
4 | #include <linux/init.h> | ||
5 | #include <linux/device.h> | ||
6 | |||
7 | /* | ||
8 | * Declaration for the various functions exported by the | ||
9 | * mpc83xx_* files. Mostly for use by mpc83xx_setup | ||
10 | */ | ||
11 | |||
12 | extern int add_bridge(struct device_node *dev); | ||
13 | |||
14 | #endif /* __MPC83XX_H__ */ | ||
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c new file mode 100644 index 000000000000..469cdacc5bd4 --- /dev/null +++ b/arch/powerpc/platforms/83xx/pci.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * FSL SoC setup code | ||
3 | * | ||
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/stddef.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/module.h> | ||
21 | |||
22 | #include <asm/system.h> | ||
23 | #include <asm/atomic.h> | ||
24 | #include <asm/io.h> | ||
25 | #include <asm/pci-bridge.h> | ||
26 | #include <asm/prom.h> | ||
27 | #include <sysdev/fsl_soc.h> | ||
28 | |||
29 | #undef DEBUG | ||
30 | |||
31 | #ifdef DEBUG | ||
32 | #define DBG(x...) printk(x) | ||
33 | #else | ||
34 | #define DBG(x...) | ||
35 | #endif | ||
36 | |||
37 | int mpc83xx_pci2_busno; | ||
38 | |||
39 | #ifdef CONFIG_PCI | ||
40 | int __init add_bridge(struct device_node *dev) | ||
41 | { | ||
42 | int len; | ||
43 | struct pci_controller *hose; | ||
44 | struct resource rsrc; | ||
45 | int *bus_range; | ||
46 | int primary = 1, has_address = 0; | ||
47 | phys_addr_t immr = get_immrbase(); | ||
48 | |||
49 | DBG("Adding PCI host bridge %s\n", dev->full_name); | ||
50 | |||
51 | /* Fetch host bridge registers address */ | ||
52 | has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); | ||
53 | |||
54 | /* Get bus range if any */ | ||
55 | bus_range = (int *) get_property(dev, "bus-range", &len); | ||
56 | if (bus_range == NULL || len < 2 * sizeof(int)) { | ||
57 | printk(KERN_WARNING "Can't get bus-range for %s, assume" | ||
58 | " bus 0\n", dev->full_name); | ||
59 | } | ||
60 | |||
61 | hose = pcibios_alloc_controller(); | ||
62 | if (!hose) | ||
63 | return -ENOMEM; | ||
64 | hose->arch_data = dev; | ||
65 | hose->set_cfg_type = 1; | ||
66 | |||
67 | hose->first_busno = bus_range ? bus_range[0] : 0; | ||
68 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | ||
69 | |||
70 | /* MPC83xx supports up to two host controllers one at 0x8500 from immrbar | ||
71 | * the other at 0x8600, we consider the 0x8500 the primary controller | ||
72 | */ | ||
73 | /* PCI 1 */ | ||
74 | if ((rsrc.start & 0xfffff) == 0x8500) { | ||
75 | setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304); | ||
76 | } | ||
77 | /* PCI 2*/ | ||
78 | if ((rsrc.start & 0xfffff) == 0x8600) { | ||
79 | setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384); | ||
80 | primary = 0; | ||
81 | hose->bus_offset = hose->first_busno; | ||
82 | mpc83xx_pci2_busno = hose->first_busno; | ||
83 | } | ||
84 | |||
85 | printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%08lx. " | ||
86 | "Firmware bus number: %d->%d\n", | ||
87 | rsrc.start, hose->first_busno, hose->last_busno); | ||
88 | |||
89 | DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", | ||
90 | hose, hose->cfg_addr, hose->cfg_data); | ||
91 | |||
92 | /* Interpret the "ranges" property */ | ||
93 | /* This also maps the I/O region and sets isa_io/mem_base */ | ||
94 | pci_process_bridge_OF_ranges(hose, dev, primary); | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | #endif | ||
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 82c429d487f3..00c52f27ef4f 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c | |||
@@ -135,12 +135,13 @@ int __init | |||
135 | hydra_init(void) | 135 | hydra_init(void) |
136 | { | 136 | { |
137 | struct device_node *np; | 137 | struct device_node *np; |
138 | struct resource r; | ||
138 | 139 | ||
139 | np = find_devices("mac-io"); | 140 | np = find_devices("mac-io"); |
140 | if (np == NULL || np->n_addrs == 0) | 141 | if (np == NULL || of_address_to_resource(np, 0, &r)) |
141 | return 0; | 142 | return 0; |
142 | Hydra = ioremap(np->addrs[0].address, np->addrs[0].size); | 143 | Hydra = ioremap(r.start, r.end-r.start); |
143 | printk("Hydra Mac I/O at %lx\n", np->addrs[0].address); | 144 | printk("Hydra Mac I/O at %lx\n", r.start); |
144 | printk("Hydra Feature_Control was %x", | 145 | printk("Hydra Feature_Control was %x", |
145 | in_le32(&Hydra->Feature_Control)); | 146 | in_le32(&Hydra->Feature_Control)); |
146 | out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN | | 147 | out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN | |
@@ -177,18 +178,24 @@ setup_python(struct pci_controller *hose, struct device_node *dev) | |||
177 | { | 178 | { |
178 | u32 __iomem *reg; | 179 | u32 __iomem *reg; |
179 | u32 val; | 180 | u32 val; |
180 | unsigned long addr = dev->addrs[0].address; | 181 | struct resource r; |
181 | 182 | ||
182 | setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010); | 183 | if (of_address_to_resource(dev, 0, &r)) { |
184 | printk(KERN_ERR "No address for Python PCI controller\n"); | ||
185 | return; | ||
186 | } | ||
183 | 187 | ||
184 | /* Clear the magic go-slow bit */ | 188 | /* Clear the magic go-slow bit */ |
185 | reg = ioremap(dev->addrs[0].address + 0xf6000, 0x40); | 189 | reg = ioremap(r.start + 0xf6000, 0x40); |
190 | BUG_ON(!reg); | ||
186 | val = in_be32(®[12]); | 191 | val = in_be32(®[12]); |
187 | if (val & PRG_CL_RESET_VALID) { | 192 | if (val & PRG_CL_RESET_VALID) { |
188 | out_be32(®[12], val & ~PRG_CL_RESET_VALID); | 193 | out_be32(®[12], val & ~PRG_CL_RESET_VALID); |
189 | in_be32(®[12]); | 194 | in_be32(®[12]); |
190 | } | 195 | } |
191 | iounmap(reg); | 196 | iounmap(reg); |
197 | |||
198 | setup_indirect_pci(hose, r.start + 0xf8000, r.start + 0xf8010); | ||
192 | } | 199 | } |
193 | 200 | ||
194 | /* Marvell Discovery II based Pegasos 2 */ | 201 | /* Marvell Discovery II based Pegasos 2 */ |
@@ -218,7 +225,7 @@ chrp_find_bridges(void) | |||
218 | char *model, *machine; | 225 | char *model, *machine; |
219 | int is_longtrail = 0, is_mot = 0, is_pegasos = 0; | 226 | int is_longtrail = 0, is_mot = 0, is_pegasos = 0; |
220 | struct device_node *root = find_path_device("/"); | 227 | struct device_node *root = find_path_device("/"); |
221 | 228 | struct resource r; | |
222 | /* | 229 | /* |
223 | * The PCI host bridge nodes on some machines don't have | 230 | * The PCI host bridge nodes on some machines don't have |
224 | * properties to adequately identify them, so we have to | 231 | * properties to adequately identify them, so we have to |
@@ -238,7 +245,7 @@ chrp_find_bridges(void) | |||
238 | continue; | 245 | continue; |
239 | ++index; | 246 | ++index; |
240 | /* The GG2 bridge on the LongTrail doesn't have an address */ | 247 | /* The GG2 bridge on the LongTrail doesn't have an address */ |
241 | if (dev->n_addrs < 1 && !is_longtrail) { | 248 | if (of_address_to_resource(dev, 0, &r) && !is_longtrail) { |
242 | printk(KERN_WARNING "Can't use %s: no address\n", | 249 | printk(KERN_WARNING "Can't use %s: no address\n", |
243 | dev->full_name); | 250 | dev->full_name); |
244 | continue; | 251 | continue; |
@@ -255,8 +262,8 @@ chrp_find_bridges(void) | |||
255 | printk(KERN_INFO "PCI buses %d..%d", | 262 | printk(KERN_INFO "PCI buses %d..%d", |
256 | bus_range[0], bus_range[1]); | 263 | bus_range[0], bus_range[1]); |
257 | printk(" controlled by %s", dev->type); | 264 | printk(" controlled by %s", dev->type); |
258 | if (dev->n_addrs > 0) | 265 | if (!is_longtrail) |
259 | printk(" at %lx", dev->addrs[0].address); | 266 | printk(" at %lx", r.start); |
260 | printk("\n"); | 267 | printk("\n"); |
261 | 268 | ||
262 | hose = pcibios_alloc_controller(); | 269 | hose = pcibios_alloc_controller(); |
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 4ec8ba737e7d..2dc87aa5962f 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -352,9 +352,10 @@ static void __init chrp_find_openpic(void) | |||
352 | opaddr = opprop[na-1]; /* assume 32-bit */ | 352 | opaddr = opprop[na-1]; /* assume 32-bit */ |
353 | oplen /= na * sizeof(unsigned int); | 353 | oplen /= na * sizeof(unsigned int); |
354 | } else { | 354 | } else { |
355 | if (np->n_addrs == 0) | 355 | struct resource r; |
356 | if (of_address_to_resource(np, 0, &r)) | ||
356 | return; | 357 | return; |
357 | opaddr = np->addrs[0].address; | 358 | opaddr = r.start; |
358 | oplen = 0; | 359 | oplen = 0; |
359 | } | 360 | } |
360 | 361 | ||
@@ -377,7 +378,7 @@ static void __init chrp_find_openpic(void) | |||
377 | */ | 378 | */ |
378 | if (oplen < len) { | 379 | if (oplen < len) { |
379 | printk(KERN_ERR "Insufficient addresses for distributed" | 380 | printk(KERN_ERR "Insufficient addresses for distributed" |
380 | " OpenPIC (%d < %d)\n", np->n_addrs, len); | 381 | " OpenPIC (%d < %d)\n", oplen, len); |
381 | len = oplen; | 382 | len = oplen; |
382 | } | 383 | } |
383 | 384 | ||
diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 737ee5d9f0aa..36a0f97bb7b1 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/mc146818rtc.h> | 21 | #include <linux/mc146818rtc.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/bcd.h> | 23 | #include <linux/bcd.h> |
24 | #include <linux/ioport.h> | ||
24 | 25 | ||
25 | #include <asm/io.h> | 26 | #include <asm/io.h> |
26 | #include <asm/nvram.h> | 27 | #include <asm/nvram.h> |
@@ -37,14 +38,16 @@ static int nvram_data = NVRAM_DATA; | |||
37 | long __init chrp_time_init(void) | 38 | long __init chrp_time_init(void) |
38 | { | 39 | { |
39 | struct device_node *rtcs; | 40 | struct device_node *rtcs; |
41 | struct resource r; | ||
40 | int base; | 42 | int base; |
41 | 43 | ||
42 | rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); | 44 | rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); |
43 | if (rtcs == NULL) | 45 | if (rtcs == NULL) |
44 | rtcs = find_compatible_devices("rtc", "ds1385-rtc"); | 46 | rtcs = find_compatible_devices("rtc", "ds1385-rtc"); |
45 | if (rtcs == NULL || rtcs->addrs == NULL) | 47 | if (rtcs == NULL || of_address_to_resource(rtcs, 0, &r)) |
46 | return 0; | 48 | return 0; |
47 | base = rtcs->addrs[0].address; | 49 | |
50 | base = r.start; | ||
48 | nvram_as1 = 0; | 51 | nvram_as1 = 0; |
49 | nvram_as0 = base; | 52 | nvram_as0 = base; |
50 | nvram_data = base + 1; | 53 | nvram_data = base + 1; |
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 83442ea77476..be3fbfc24e6c 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c | |||
@@ -334,14 +334,12 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus, | |||
334 | */ | 334 | */ |
335 | int iSeries_get_irq(struct pt_regs *regs) | 335 | int iSeries_get_irq(struct pt_regs *regs) |
336 | { | 336 | { |
337 | struct paca_struct *lpaca; | ||
338 | /* -2 means ignore this interrupt */ | 337 | /* -2 means ignore this interrupt */ |
339 | int irq = -2; | 338 | int irq = -2; |
340 | 339 | ||
341 | lpaca = get_paca(); | ||
342 | #ifdef CONFIG_SMP | 340 | #ifdef CONFIG_SMP |
343 | if (lpaca->lppaca.int_dword.fields.ipi_cnt) { | 341 | if (get_lppaca()->int_dword.fields.ipi_cnt) { |
344 | lpaca->lppaca.int_dword.fields.ipi_cnt = 0; | 342 | get_lppaca()->int_dword.fields.ipi_cnt = 0; |
345 | iSeries_smp_message_recv(regs); | 343 | iSeries_smp_message_recv(regs); |
346 | } | 344 | } |
347 | #endif /* CONFIG_SMP */ | 345 | #endif /* CONFIG_SMP */ |
diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S index dfe7aa1ba098..7641fc7e550a 100644 --- a/arch/powerpc/platforms/iseries/misc.S +++ b/arch/powerpc/platforms/iseries/misc.S | |||
@@ -44,7 +44,8 @@ _GLOBAL(local_irq_restore) | |||
44 | /* Check pending interrupts */ | 44 | /* Check pending interrupts */ |
45 | /* A decrementer, IPI or PMC interrupt may have occurred | 45 | /* A decrementer, IPI or PMC interrupt may have occurred |
46 | * while we were in the hypervisor (which enables) */ | 46 | * while we were in the hypervisor (which enables) */ |
47 | ld r4,PACALPPACA+LPPACAANYINT(r13) | 47 | ld r4,PACALPPACAPTR(r13) |
48 | ld r4,LPPACAANYINT(r4) | ||
48 | cmpdi r4,0 | 49 | cmpdi r4,0 |
49 | beqlr | 50 | beqlr |
50 | 51 | ||
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index c6bbe5c25107..3f8790146b00 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c | |||
@@ -538,7 +538,7 @@ static unsigned long __init build_iSeries_Memory_Map(void) | |||
538 | */ | 538 | */ |
539 | static void __init iSeries_setup_arch(void) | 539 | static void __init iSeries_setup_arch(void) |
540 | { | 540 | { |
541 | if (get_paca()->lppaca.shared_proc) { | 541 | if (get_lppaca()->shared_proc) { |
542 | ppc_md.idle_loop = iseries_shared_idle; | 542 | ppc_md.idle_loop = iseries_shared_idle; |
543 | printk(KERN_INFO "Using shared processor idle loop\n"); | 543 | printk(KERN_INFO "Using shared processor idle loop\n"); |
544 | } else { | 544 | } else { |
@@ -647,7 +647,7 @@ static void yield_shared_processor(void) | |||
647 | * The decrementer stops during the yield. Force a fake decrementer | 647 | * The decrementer stops during the yield. Force a fake decrementer |
648 | * here and let the timer_interrupt code sort out the actual time. | 648 | * here and let the timer_interrupt code sort out the actual time. |
649 | */ | 649 | */ |
650 | get_paca()->lppaca.int_dword.fields.decr_int = 1; | 650 | get_lppaca()->int_dword.fields.decr_int = 1; |
651 | process_iSeries_events(); | 651 | process_iSeries_events(); |
652 | } | 652 | } |
653 | 653 | ||
@@ -883,7 +883,7 @@ void dt_cpus(struct iseries_flat_dt *dt) | |||
883 | pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); | 883 | pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); |
884 | 884 | ||
885 | for (i = 0; i < NR_CPUS; i++) { | 885 | for (i = 0; i < NR_CPUS; i++) { |
886 | if (paca[i].lppaca.dyn_proc_status >= 2) | 886 | if (lppaca[i].dyn_proc_status >= 2) |
887 | continue; | 887 | continue; |
888 | 888 | ||
889 | snprintf(p, 32 - (p - buf), "@%d", i); | 889 | snprintf(p, 32 - (p - buf), "@%d", i); |
@@ -891,7 +891,7 @@ void dt_cpus(struct iseries_flat_dt *dt) | |||
891 | 891 | ||
892 | dt_prop_str(dt, "device_type", "cpu"); | 892 | dt_prop_str(dt, "device_type", "cpu"); |
893 | 893 | ||
894 | index = paca[i].lppaca.dyn_hv_phys_proc_index; | 894 | index = lppaca[i].dyn_hv_phys_proc_index; |
895 | d = &xIoHriProcessorVpd[index]; | 895 | d = &xIoHriProcessorVpd[index]; |
896 | 896 | ||
897 | dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); | 897 | dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); |
diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c index fcb094ec6aec..6f9d407a709f 100644 --- a/arch/powerpc/platforms/iseries/smp.c +++ b/arch/powerpc/platforms/iseries/smp.c | |||
@@ -91,7 +91,7 @@ static void smp_iSeries_kick_cpu(int nr) | |||
91 | BUG_ON((nr < 0) || (nr >= NR_CPUS)); | 91 | BUG_ON((nr < 0) || (nr >= NR_CPUS)); |
92 | 92 | ||
93 | /* Verify that our partition has a processor nr */ | 93 | /* Verify that our partition has a processor nr */ |
94 | if (paca[nr].lppaca.dyn_proc_status >= 2) | 94 | if (lppaca[nr].dyn_proc_status >= 2) |
95 | return; | 95 | return; |
96 | 96 | ||
97 | /* The processor is currently spinning, waiting | 97 | /* The processor is currently spinning, waiting |
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 1fe445ab78a6..8952528d31ac 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -254,11 +254,11 @@ out: | |||
254 | void vpa_init(int cpu) | 254 | void vpa_init(int cpu) |
255 | { | 255 | { |
256 | int hwcpu = get_hard_smp_processor_id(cpu); | 256 | int hwcpu = get_hard_smp_processor_id(cpu); |
257 | unsigned long vpa = __pa(&paca[cpu].lppaca); | 257 | unsigned long vpa = __pa(&lppaca[cpu]); |
258 | long ret; | 258 | long ret; |
259 | 259 | ||
260 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) | 260 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) |
261 | paca[cpu].lppaca.vmxregs_in_use = 1; | 261 | lppaca[cpu].vmxregs_in_use = 1; |
262 | 262 | ||
263 | ret = register_vpa(hwcpu, vpa); | 263 | ret = register_vpa(hwcpu, vpa); |
264 | 264 | ||
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index d8864164dbe8..86cfa6ecdcf3 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
@@ -350,6 +350,100 @@ static int do_remove_node(char *buf) | |||
350 | return rv; | 350 | return rv; |
351 | } | 351 | } |
352 | 352 | ||
353 | static char *parse_node(char *buf, size_t bufsize, struct device_node **npp) | ||
354 | { | ||
355 | char *handle_str; | ||
356 | phandle handle; | ||
357 | *npp = NULL; | ||
358 | |||
359 | handle_str = buf; | ||
360 | |||
361 | buf = strchr(buf, ' '); | ||
362 | if (!buf) | ||
363 | return NULL; | ||
364 | *buf = '\0'; | ||
365 | buf++; | ||
366 | |||
367 | handle = simple_strtoul(handle_str, NULL, 10); | ||
368 | |||
369 | *npp = of_find_node_by_phandle(handle); | ||
370 | return buf; | ||
371 | } | ||
372 | |||
373 | static int do_add_property(char *buf, size_t bufsize) | ||
374 | { | ||
375 | struct property *prop = NULL; | ||
376 | struct device_node *np; | ||
377 | unsigned char *value; | ||
378 | char *name, *end; | ||
379 | int length; | ||
380 | end = buf + bufsize; | ||
381 | buf = parse_node(buf, bufsize, &np); | ||
382 | |||
383 | if (!np) | ||
384 | return -ENODEV; | ||
385 | |||
386 | if (parse_next_property(buf, end, &name, &length, &value) == NULL) | ||
387 | return -EINVAL; | ||
388 | |||
389 | prop = new_property(name, length, value, NULL); | ||
390 | if (!prop) | ||
391 | return -ENOMEM; | ||
392 | |||
393 | prom_add_property(np, prop); | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | static int do_remove_property(char *buf, size_t bufsize) | ||
399 | { | ||
400 | struct device_node *np; | ||
401 | char *tmp; | ||
402 | struct property *prop; | ||
403 | buf = parse_node(buf, bufsize, &np); | ||
404 | |||
405 | if (!np) | ||
406 | return -ENODEV; | ||
407 | |||
408 | tmp = strchr(buf,' '); | ||
409 | if (tmp) | ||
410 | *tmp = '\0'; | ||
411 | |||
412 | if (strlen(buf) == 0) | ||
413 | return -EINVAL; | ||
414 | |||
415 | prop = of_find_property(np, buf, NULL); | ||
416 | |||
417 | return prom_remove_property(np, prop); | ||
418 | } | ||
419 | |||
420 | static int do_update_property(char *buf, size_t bufsize) | ||
421 | { | ||
422 | struct device_node *np; | ||
423 | unsigned char *value; | ||
424 | char *name, *end; | ||
425 | int length; | ||
426 | struct property *newprop, *oldprop; | ||
427 | buf = parse_node(buf, bufsize, &np); | ||
428 | end = buf + bufsize; | ||
429 | |||
430 | if (!np) | ||
431 | return -ENODEV; | ||
432 | |||
433 | if (parse_next_property(buf, end, &name, &length, &value) == NULL) | ||
434 | return -EINVAL; | ||
435 | |||
436 | newprop = new_property(name, length, value, NULL); | ||
437 | if (!newprop) | ||
438 | return -ENOMEM; | ||
439 | |||
440 | oldprop = of_find_property(np, name,NULL); | ||
441 | if (!oldprop) | ||
442 | return -ENODEV; | ||
443 | |||
444 | return prom_update_property(np, newprop, oldprop); | ||
445 | } | ||
446 | |||
353 | /** | 447 | /** |
354 | * ofdt_write - perform operations on the Open Firmware device tree | 448 | * ofdt_write - perform operations on the Open Firmware device tree |
355 | * | 449 | * |
@@ -392,6 +486,12 @@ static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t coun | |||
392 | rv = do_add_node(tmp, count - (tmp - kbuf)); | 486 | rv = do_add_node(tmp, count - (tmp - kbuf)); |
393 | else if (!strcmp(kbuf, "remove_node")) | 487 | else if (!strcmp(kbuf, "remove_node")) |
394 | rv = do_remove_node(tmp); | 488 | rv = do_remove_node(tmp); |
489 | else if (!strcmp(kbuf, "add_property")) | ||
490 | rv = do_add_property(tmp, count - (tmp - kbuf)); | ||
491 | else if (!strcmp(kbuf, "remove_property")) | ||
492 | rv = do_remove_property(tmp, count - (tmp - kbuf)); | ||
493 | else if (!strcmp(kbuf, "update_property")) | ||
494 | rv = do_update_property(tmp, count - (tmp - kbuf)); | ||
395 | else | 495 | else |
396 | rv = -EINVAL; | 496 | rv = -EINVAL; |
397 | out: | 497 | out: |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 68b7f086d63d..da6cebaf72cd 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -190,7 +190,7 @@ static void pseries_lpar_enable_pmcs(void) | |||
190 | 190 | ||
191 | /* instruct hypervisor to maintain PMCs */ | 191 | /* instruct hypervisor to maintain PMCs */ |
192 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) | 192 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) |
193 | get_paca()->lppaca.pmcregs_in_use = 1; | 193 | get_lppaca()->pmcregs_in_use = 1; |
194 | } | 194 | } |
195 | 195 | ||
196 | static void __init pSeries_setup_arch(void) | 196 | static void __init pSeries_setup_arch(void) |
@@ -234,7 +234,7 @@ static void __init pSeries_setup_arch(void) | |||
234 | /* Choose an idle loop */ | 234 | /* Choose an idle loop */ |
235 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { | 235 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { |
236 | vpa_init(boot_cpuid); | 236 | vpa_init(boot_cpuid); |
237 | if (get_paca()->lppaca.shared_proc) { | 237 | if (get_lppaca()->shared_proc) { |
238 | printk(KERN_INFO "Using shared processor idle loop\n"); | 238 | printk(KERN_INFO "Using shared processor idle loop\n"); |
239 | ppc_md.idle_loop = pseries_shared_idle; | 239 | ppc_md.idle_loop = pseries_shared_idle; |
240 | } else { | 240 | } else { |
@@ -444,10 +444,10 @@ DECLARE_PER_CPU(unsigned long, smt_snooze_delay); | |||
444 | 444 | ||
445 | static inline void dedicated_idle_sleep(unsigned int cpu) | 445 | static inline void dedicated_idle_sleep(unsigned int cpu) |
446 | { | 446 | { |
447 | struct paca_struct *ppaca = &paca[cpu ^ 1]; | 447 | struct lppaca *plppaca = &lppaca[cpu ^ 1]; |
448 | 448 | ||
449 | /* Only sleep if the other thread is not idle */ | 449 | /* Only sleep if the other thread is not idle */ |
450 | if (!(ppaca->lppaca.idle)) { | 450 | if (!(plppaca->idle)) { |
451 | local_irq_disable(); | 451 | local_irq_disable(); |
452 | 452 | ||
453 | /* | 453 | /* |
@@ -480,7 +480,6 @@ static inline void dedicated_idle_sleep(unsigned int cpu) | |||
480 | 480 | ||
481 | static void pseries_dedicated_idle(void) | 481 | static void pseries_dedicated_idle(void) |
482 | { | 482 | { |
483 | struct paca_struct *lpaca = get_paca(); | ||
484 | unsigned int cpu = smp_processor_id(); | 483 | unsigned int cpu = smp_processor_id(); |
485 | unsigned long start_snooze; | 484 | unsigned long start_snooze; |
486 | unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay); | 485 | unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay); |
@@ -491,7 +490,7 @@ static void pseries_dedicated_idle(void) | |||
491 | * Indicate to the HV that we are idle. Now would be | 490 | * Indicate to the HV that we are idle. Now would be |
492 | * a good time to find other work to dispatch. | 491 | * a good time to find other work to dispatch. |
493 | */ | 492 | */ |
494 | lpaca->lppaca.idle = 1; | 493 | get_lppaca()->idle = 1; |
495 | 494 | ||
496 | if (!need_resched()) { | 495 | if (!need_resched()) { |
497 | start_snooze = get_tb() + | 496 | start_snooze = get_tb() + |
@@ -518,7 +517,7 @@ static void pseries_dedicated_idle(void) | |||
518 | HMT_medium(); | 517 | HMT_medium(); |
519 | } | 518 | } |
520 | 519 | ||
521 | lpaca->lppaca.idle = 0; | 520 | get_lppaca()->idle = 0; |
522 | ppc64_runlatch_on(); | 521 | ppc64_runlatch_on(); |
523 | 522 | ||
524 | preempt_enable_no_resched(); | 523 | preempt_enable_no_resched(); |
@@ -532,7 +531,6 @@ static void pseries_dedicated_idle(void) | |||
532 | 531 | ||
533 | static void pseries_shared_idle(void) | 532 | static void pseries_shared_idle(void) |
534 | { | 533 | { |
535 | struct paca_struct *lpaca = get_paca(); | ||
536 | unsigned int cpu = smp_processor_id(); | 534 | unsigned int cpu = smp_processor_id(); |
537 | 535 | ||
538 | while (1) { | 536 | while (1) { |
@@ -540,7 +538,7 @@ static void pseries_shared_idle(void) | |||
540 | * Indicate to the HV that we are idle. Now would be | 538 | * Indicate to the HV that we are idle. Now would be |
541 | * a good time to find other work to dispatch. | 539 | * a good time to find other work to dispatch. |
542 | */ | 540 | */ |
543 | lpaca->lppaca.idle = 1; | 541 | get_lppaca()->idle = 1; |
544 | 542 | ||
545 | while (!need_resched() && !cpu_is_offline(cpu)) { | 543 | while (!need_resched() && !cpu_is_offline(cpu)) { |
546 | local_irq_disable(); | 544 | local_irq_disable(); |
@@ -564,7 +562,7 @@ static void pseries_shared_idle(void) | |||
564 | HMT_medium(); | 562 | HMT_medium(); |
565 | } | 563 | } |
566 | 564 | ||
567 | lpaca->lppaca.idle = 0; | 565 | get_lppaca()->idle = 0; |
568 | ppc64_runlatch_on(); | 566 | ppc64_runlatch_on(); |
569 | 567 | ||
570 | preempt_enable_no_resched(); | 568 | preempt_enable_no_resched(); |
@@ -588,7 +586,7 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) | |||
588 | { | 586 | { |
589 | /* Don't risk a hypervisor call if we're crashing */ | 587 | /* Don't risk a hypervisor call if we're crashing */ |
590 | if (!crash_shutdown) { | 588 | if (!crash_shutdown) { |
591 | unsigned long vpa = __pa(&get_paca()->lppaca); | 589 | unsigned long vpa = __pa(get_lppaca()); |
592 | 590 | ||
593 | if (unregister_vpa(hard_smp_processor_id(), vpa)) { | 591 | if (unregister_vpa(hard_smp_processor_id(), vpa)) { |
594 | printk("VPA deregistration of cpu %u (hw_cpu_id %d) " | 592 | printk("VPA deregistration of cpu %u (hw_cpu_id %d) " |
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 0ae841347a09..4c2b356774ea 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
@@ -7,3 +7,4 @@ obj-$(CONFIG_40x) += dcr.o | |||
7 | obj-$(CONFIG_U3_DART) += dart_iommu.o | 7 | obj-$(CONFIG_U3_DART) += dart_iommu.o |
8 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o | 8 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o |
9 | obj-$(CONFIG_PPC_83xx) += ipic.o | 9 | obj-$(CONFIG_PPC_83xx) += ipic.o |
10 | obj-$(CONFIG_FSL_SOC) += fsl_soc.o | ||
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c new file mode 100644 index 000000000000..064c9de47732 --- /dev/null +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
@@ -0,0 +1,317 @@ | |||
1 | /* | ||
2 | * FSL SoC setup code | ||
3 | * | ||
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/stddef.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/major.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/device.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/fsl_devices.h> | ||
24 | |||
25 | #include <asm/system.h> | ||
26 | #include <asm/atomic.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/irq.h> | ||
29 | #include <asm/prom.h> | ||
30 | #include <sysdev/fsl_soc.h> | ||
31 | #include <mm/mmu_decl.h> | ||
32 | |||
33 | static phys_addr_t immrbase = -1; | ||
34 | |||
35 | phys_addr_t get_immrbase(void) | ||
36 | { | ||
37 | struct device_node *soc; | ||
38 | |||
39 | if (immrbase != -1) | ||
40 | return immrbase; | ||
41 | |||
42 | soc = of_find_node_by_type(NULL, "soc"); | ||
43 | if (soc != 0) { | ||
44 | unsigned int size; | ||
45 | void *prop = get_property(soc, "reg", &size); | ||
46 | immrbase = of_translate_address(soc, prop); | ||
47 | of_node_put(soc); | ||
48 | }; | ||
49 | |||
50 | return immrbase; | ||
51 | } | ||
52 | EXPORT_SYMBOL(get_immrbase); | ||
53 | |||
54 | static const char * gfar_tx_intr = "tx"; | ||
55 | static const char * gfar_rx_intr = "rx"; | ||
56 | static const char * gfar_err_intr = "error"; | ||
57 | |||
58 | static int __init gfar_of_init(void) | ||
59 | { | ||
60 | struct device_node *np; | ||
61 | unsigned int i; | ||
62 | struct platform_device *mdio_dev, *gfar_dev; | ||
63 | struct resource res; | ||
64 | int ret; | ||
65 | |||
66 | for (np = NULL, i = 0; (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL; i++) { | ||
67 | int k; | ||
68 | struct device_node *child = NULL; | ||
69 | struct gianfar_mdio_data mdio_data; | ||
70 | |||
71 | memset(&res, 0, sizeof(res)); | ||
72 | memset(&mdio_data, 0, sizeof(mdio_data)); | ||
73 | |||
74 | ret = of_address_to_resource(np, 0, &res); | ||
75 | if (ret) | ||
76 | goto mdio_err; | ||
77 | |||
78 | mdio_dev = platform_device_register_simple("fsl-gianfar_mdio", res.start, &res, 1); | ||
79 | if (IS_ERR(mdio_dev)) { | ||
80 | ret = PTR_ERR(mdio_dev); | ||
81 | goto mdio_err; | ||
82 | } | ||
83 | |||
84 | for (k = 0; k < 32; k++) | ||
85 | mdio_data.irq[k] = -1; | ||
86 | |||
87 | while ((child = of_get_next_child(np, child)) != NULL) { | ||
88 | if (child->n_intrs) { | ||
89 | u32 *id = (u32 *) get_property(child, "reg", NULL); | ||
90 | mdio_data.irq[*id] = child->intrs[0].line; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | ret = platform_device_add_data(mdio_dev, &mdio_data, sizeof(struct gianfar_mdio_data)); | ||
95 | if (ret) | ||
96 | goto mdio_unreg; | ||
97 | } | ||
98 | |||
99 | for (np = NULL, i = 0; (np = of_find_compatible_node(np, "network", "gianfar")) != NULL; i++) { | ||
100 | struct resource r[4]; | ||
101 | struct device_node *phy, *mdio; | ||
102 | struct gianfar_platform_data gfar_data; | ||
103 | unsigned int *id; | ||
104 | char *model; | ||
105 | void *mac_addr; | ||
106 | phandle *ph; | ||
107 | |||
108 | memset(r, 0, sizeof(r)); | ||
109 | memset(&gfar_data, 0, sizeof(gfar_data)); | ||
110 | |||
111 | ret = of_address_to_resource(np, 0, &r[0]); | ||
112 | if (ret) | ||
113 | goto gfar_err; | ||
114 | |||
115 | r[1].start = np->intrs[0].line; | ||
116 | r[1].end = np->intrs[0].line; | ||
117 | r[1].flags = IORESOURCE_IRQ; | ||
118 | |||
119 | model = get_property(np, "model", NULL); | ||
120 | |||
121 | /* If we aren't the FEC we have multiple interrupts */ | ||
122 | if (model && strcasecmp(model, "FEC")) { | ||
123 | r[1].name = gfar_tx_intr; | ||
124 | |||
125 | r[2].name = gfar_rx_intr; | ||
126 | r[2].start = np->intrs[1].line; | ||
127 | r[2].end = np->intrs[1].line; | ||
128 | r[2].flags = IORESOURCE_IRQ; | ||
129 | |||
130 | r[3].name = gfar_err_intr; | ||
131 | r[3].start = np->intrs[2].line; | ||
132 | r[3].end = np->intrs[2].line; | ||
133 | r[3].flags = IORESOURCE_IRQ; | ||
134 | } | ||
135 | |||
136 | gfar_dev = platform_device_register_simple("fsl-gianfar", i, &r[0], np->n_intrs + 1); | ||
137 | |||
138 | if (IS_ERR(gfar_dev)) { | ||
139 | ret = PTR_ERR(gfar_dev); | ||
140 | goto gfar_err; | ||
141 | } | ||
142 | |||
143 | mac_addr = get_property(np, "address", NULL); | ||
144 | memcpy(gfar_data.mac_addr, mac_addr, 6); | ||
145 | |||
146 | if (model && !strcasecmp(model, "TSEC")) | ||
147 | gfar_data.device_flags = | ||
148 | FSL_GIANFAR_DEV_HAS_GIGABIT | | ||
149 | FSL_GIANFAR_DEV_HAS_COALESCE | | ||
150 | FSL_GIANFAR_DEV_HAS_RMON | | ||
151 | FSL_GIANFAR_DEV_HAS_MULTI_INTR; | ||
152 | if (model && !strcasecmp(model, "eTSEC")) | ||
153 | gfar_data.device_flags = | ||
154 | FSL_GIANFAR_DEV_HAS_GIGABIT | | ||
155 | FSL_GIANFAR_DEV_HAS_COALESCE | | ||
156 | FSL_GIANFAR_DEV_HAS_RMON | | ||
157 | FSL_GIANFAR_DEV_HAS_MULTI_INTR | | ||
158 | FSL_GIANFAR_DEV_HAS_CSUM | | ||
159 | FSL_GIANFAR_DEV_HAS_VLAN | | ||
160 | FSL_GIANFAR_DEV_HAS_EXTENDED_HASH; | ||
161 | |||
162 | ph = (phandle *) get_property(np, "phy-handle", NULL); | ||
163 | phy = of_find_node_by_phandle(*ph); | ||
164 | |||
165 | if (phy == NULL) { | ||
166 | ret = -ENODEV; | ||
167 | goto gfar_unreg; | ||
168 | } | ||
169 | |||
170 | mdio = of_get_parent(phy); | ||
171 | |||
172 | id = (u32 *) get_property(phy, "reg", NULL); | ||
173 | ret = of_address_to_resource(mdio, 0, &res); | ||
174 | if (ret) { | ||
175 | of_node_put(phy); | ||
176 | of_node_put(mdio); | ||
177 | goto gfar_unreg; | ||
178 | } | ||
179 | |||
180 | gfar_data.phy_id = *id; | ||
181 | gfar_data.bus_id = res.start; | ||
182 | |||
183 | of_node_put(phy); | ||
184 | of_node_put(mdio); | ||
185 | |||
186 | ret = platform_device_add_data(gfar_dev, &gfar_data, sizeof(struct gianfar_platform_data)); | ||
187 | if (ret) | ||
188 | goto gfar_unreg; | ||
189 | } | ||
190 | |||
191 | return 0; | ||
192 | |||
193 | mdio_unreg: | ||
194 | platform_device_unregister(mdio_dev); | ||
195 | mdio_err: | ||
196 | return ret; | ||
197 | |||
198 | gfar_unreg: | ||
199 | platform_device_unregister(gfar_dev); | ||
200 | gfar_err: | ||
201 | return ret; | ||
202 | } | ||
203 | arch_initcall(gfar_of_init); | ||
204 | |||
205 | static int __init fsl_i2c_of_init(void) | ||
206 | { | ||
207 | struct device_node *np; | ||
208 | unsigned int i; | ||
209 | struct platform_device *i2c_dev; | ||
210 | int ret; | ||
211 | |||
212 | for (np = NULL, i = 0; (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL; i++) { | ||
213 | struct resource r[2]; | ||
214 | struct fsl_i2c_platform_data i2c_data; | ||
215 | unsigned char * flags = NULL; | ||
216 | |||
217 | memset(&r, 0, sizeof(r)); | ||
218 | memset(&i2c_data, 0, sizeof(i2c_data)); | ||
219 | |||
220 | ret = of_address_to_resource(np, 0, &r[0]); | ||
221 | if (ret) | ||
222 | goto i2c_err; | ||
223 | |||
224 | r[1].start = np->intrs[0].line; | ||
225 | r[1].end = np->intrs[0].line; | ||
226 | r[1].flags = IORESOURCE_IRQ; | ||
227 | |||
228 | i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2); | ||
229 | if (IS_ERR(i2c_dev)) { | ||
230 | ret = PTR_ERR(i2c_dev); | ||
231 | goto i2c_err; | ||
232 | } | ||
233 | |||
234 | i2c_data.device_flags = 0; | ||
235 | flags = get_property(np, "dfsrr", NULL); | ||
236 | if (flags) | ||
237 | i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR; | ||
238 | |||
239 | flags = get_property(np, "fsl5200-clocking", NULL); | ||
240 | if (flags) | ||
241 | i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200; | ||
242 | |||
243 | ret = platform_device_add_data(i2c_dev, &i2c_data, sizeof(struct fsl_i2c_platform_data)); | ||
244 | if (ret) | ||
245 | goto i2c_unreg; | ||
246 | } | ||
247 | |||
248 | return 0; | ||
249 | |||
250 | i2c_unreg: | ||
251 | platform_device_unregister(i2c_dev); | ||
252 | i2c_err: | ||
253 | return ret; | ||
254 | } | ||
255 | arch_initcall(fsl_i2c_of_init); | ||
256 | |||
257 | #ifdef CONFIG_PPC_83xx | ||
258 | static int __init mpc83xx_wdt_init(void) | ||
259 | { | ||
260 | struct resource r; | ||
261 | struct device_node *soc, *np; | ||
262 | struct platform_device *dev; | ||
263 | unsigned int *freq; | ||
264 | int ret; | ||
265 | |||
266 | np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt"); | ||
267 | |||
268 | if (!np) { | ||
269 | ret = -ENODEV; | ||
270 | goto mpc83xx_wdt_nodev; | ||
271 | } | ||
272 | |||
273 | soc = of_find_node_by_type(NULL, "soc"); | ||
274 | |||
275 | if (!soc) { | ||
276 | ret = -ENODEV; | ||
277 | goto mpc83xx_wdt_nosoc; | ||
278 | } | ||
279 | |||
280 | freq = (unsigned int *)get_property(soc, "bus-frequency", NULL); | ||
281 | if (!freq) { | ||
282 | ret = -ENODEV; | ||
283 | goto mpc83xx_wdt_err; | ||
284 | } | ||
285 | |||
286 | memset(&r, 0, sizeof(r)); | ||
287 | |||
288 | ret = of_address_to_resource(np, 0, &r); | ||
289 | if (ret) | ||
290 | goto mpc83xx_wdt_err; | ||
291 | |||
292 | dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1); | ||
293 | if (IS_ERR(dev)) { | ||
294 | ret = PTR_ERR(dev); | ||
295 | goto mpc83xx_wdt_err; | ||
296 | } | ||
297 | |||
298 | ret = platform_device_add_data(dev, freq, sizeof(int)); | ||
299 | if (ret) | ||
300 | goto mpc83xx_wdt_unreg; | ||
301 | |||
302 | of_node_put(soc); | ||
303 | of_node_put(np); | ||
304 | |||
305 | return 0; | ||
306 | |||
307 | mpc83xx_wdt_unreg: | ||
308 | platform_device_unregister(dev); | ||
309 | mpc83xx_wdt_err: | ||
310 | of_node_put(soc); | ||
311 | mpc83xx_wdt_nosoc: | ||
312 | of_node_put(np); | ||
313 | mpc83xx_wdt_nodev: | ||
314 | return ret; | ||
315 | } | ||
316 | arch_initcall(mpc83xx_wdt_init); | ||
317 | #endif | ||
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h new file mode 100644 index 000000000000..c433d3f39edd --- /dev/null +++ b/arch/powerpc/sysdev/fsl_soc.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef __PPC_FSL_SOC_H | ||
2 | #define __PPC_FSL_SOC_H | ||
3 | #ifdef __KERNEL__ | ||
4 | |||
5 | extern phys_addr_t get_immrbase(void); | ||
6 | |||
7 | #endif | ||
8 | #endif | ||
diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c index ebc4db8fcc63..8ace2a1f3b48 100644 --- a/arch/ppc/4xx_io/serial_sicc.c +++ b/arch/ppc/4xx_io/serial_sicc.c | |||
@@ -215,7 +215,6 @@ static struct tty_driver *siccnormal_driver; | |||
215 | * memory if large numbers of serial ports are open. | 215 | * memory if large numbers of serial ports are open. |
216 | */ | 216 | */ |
217 | static u_char *tmp_buf; | 217 | static u_char *tmp_buf; |
218 | static DECLARE_MUTEX(tmp_buf_sem); | ||
219 | 218 | ||
220 | #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) | 219 | #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) |
221 | 220 | ||
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S index de0978742221..3e6ca7f5843f 100644 --- a/arch/ppc/kernel/head_8xx.S +++ b/arch/ppc/kernel/head_8xx.S | |||
@@ -375,6 +375,8 @@ DataStoreTLBMiss: | |||
375 | lis r11, swapper_pg_dir@h | 375 | lis r11, swapper_pg_dir@h |
376 | ori r11, r11, swapper_pg_dir@l | 376 | ori r11, r11, swapper_pg_dir@l |
377 | rlwimi r10, r11, 0, 2, 19 | 377 | rlwimi r10, r11, 0, 2, 19 |
378 | stw r12, 16(r0) | ||
379 | b LoadLargeDTLB | ||
378 | 3: | 380 | 3: |
379 | lwz r11, 0(r10) /* Get the level 1 entry */ | 381 | lwz r11, 0(r10) /* Get the level 1 entry */ |
380 | rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ | 382 | rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ |
@@ -430,6 +432,81 @@ DataStoreTLBMiss: | |||
430 | InstructionTLBError: | 432 | InstructionTLBError: |
431 | b InstructionAccess | 433 | b InstructionAccess |
432 | 434 | ||
435 | LoadLargeDTLB: | ||
436 | li r12, 0 | ||
437 | lwz r11, 0(r10) /* Get the level 1 entry */ | ||
438 | rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ | ||
439 | beq 3f /* If zero, don't try to find a pte */ | ||
440 | |||
441 | /* We have a pte table, so load fetch the pte from the table. | ||
442 | */ | ||
443 | ori r11, r11, 1 /* Set valid bit in physical L2 page */ | ||
444 | DO_8xx_CPU6(0x3b80, r3) | ||
445 | mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ | ||
446 | mfspr r10, SPRN_MD_TWC /* ....and get the pte address */ | ||
447 | lwz r10, 0(r10) /* Get the pte */ | ||
448 | |||
449 | /* Insert the Guarded flag into the TWC from the Linux PTE. | ||
450 | * It is bit 27 of both the Linux PTE and the TWC (at least | ||
451 | * I got that right :-). It will be better when we can put | ||
452 | * this into the Linux pgd/pmd and load it in the operation | ||
453 | * above. | ||
454 | */ | ||
455 | rlwimi r11, r10, 0, 27, 27 | ||
456 | |||
457 | rlwimi r12, r10, 0, 0, 9 /* extract phys. addr */ | ||
458 | mfspr r3, SPRN_MD_EPN | ||
459 | rlwinm r3, r3, 0, 0, 9 /* extract virtual address */ | ||
460 | tophys(r3, r3) | ||
461 | cmpw r3, r12 /* only use 8M page if it is a direct | ||
462 | kernel mapping */ | ||
463 | bne 1f | ||
464 | ori r11, r11, MD_PS8MEG | ||
465 | li r12, 1 | ||
466 | b 2f | ||
467 | 1: | ||
468 | li r12, 0 /* can't use 8MB TLB, so zero r12. */ | ||
469 | 2: | ||
470 | DO_8xx_CPU6(0x3b80, r3) | ||
471 | mtspr SPRN_MD_TWC, r11 | ||
472 | |||
473 | /* The Linux PTE won't go exactly into the MMU TLB. | ||
474 | * Software indicator bits 21, 22 and 28 must be clear. | ||
475 | * Software indicator bits 24, 25, 26, and 27 must be | ||
476 | * set. All other Linux PTE bits control the behavior | ||
477 | * of the MMU. | ||
478 | */ | ||
479 | 3: li r11, 0x00f0 | ||
480 | rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ | ||
481 | cmpwi r12, 1 | ||
482 | bne 4f | ||
483 | ori r10, r10, 0x8 | ||
484 | |||
485 | mfspr r12, SPRN_MD_EPN | ||
486 | lis r3, 0xff80 /* 10-19 must be clear for 8MB TLB */ | ||
487 | ori r3, r3, 0x0fff | ||
488 | and r12, r3, r12 | ||
489 | DO_8xx_CPU6(0x3780, r3) | ||
490 | mtspr SPRN_MD_EPN, r12 | ||
491 | |||
492 | lis r3, 0xff80 /* 10-19 must be clear for 8MB TLB */ | ||
493 | ori r3, r3, 0x0fff | ||
494 | and r10, r3, r10 | ||
495 | 4: | ||
496 | DO_8xx_CPU6(0x3d80, r3) | ||
497 | mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ | ||
498 | |||
499 | mfspr r10, SPRN_M_TW /* Restore registers */ | ||
500 | lwz r11, 0(r0) | ||
501 | mtcr r11 | ||
502 | lwz r11, 4(r0) | ||
503 | |||
504 | lwz r12, 16(r0) | ||
505 | #ifdef CONFIG_8xx_CPU6 | ||
506 | lwz r3, 8(r0) | ||
507 | #endif | ||
508 | rfi | ||
509 | |||
433 | /* This is the data TLB error on the MPC8xx. This could be due to | 510 | /* This is the data TLB error on the MPC8xx. This could be due to |
434 | * many reasons, including a dirty update to a pte. We can catch that | 511 | * many reasons, including a dirty update to a pte. We can catch that |
435 | * one here, but anything else is an error. First, we track down the | 512 | * one here, but anything else is an error. First, we track down the |
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 95075f99a6d4..fb0da7c209db 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c | |||
@@ -270,7 +270,6 @@ EXPORT_SYMBOL(__delay); | |||
270 | EXPORT_SYMBOL(timer_interrupt); | 270 | EXPORT_SYMBOL(timer_interrupt); |
271 | EXPORT_SYMBOL(irq_desc); | 271 | EXPORT_SYMBOL(irq_desc); |
272 | EXPORT_SYMBOL(tb_ticks_per_jiffy); | 272 | EXPORT_SYMBOL(tb_ticks_per_jiffy); |
273 | EXPORT_SYMBOL(get_wchan); | ||
274 | EXPORT_SYMBOL(console_drivers); | 273 | EXPORT_SYMBOL(console_drivers); |
275 | #ifdef CONFIG_XMON | 274 | #ifdef CONFIG_XMON |
276 | EXPORT_SYMBOL(xmon); | 275 | EXPORT_SYMBOL(xmon); |
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index 04bdc39bf47b..012e1e652c03 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c | |||
@@ -51,9 +51,6 @@ | |||
51 | 51 | ||
52 | #include <syslib/ppc83xx_setup.h> | 52 | #include <syslib/ppc83xx_setup.h> |
53 | 53 | ||
54 | static const char *GFAR_PHY_0 = "phy0:0"; | ||
55 | static const char *GFAR_PHY_1 = "phy0:1"; | ||
56 | |||
57 | #ifndef CONFIG_PCI | 54 | #ifndef CONFIG_PCI |
58 | unsigned long isa_io_base = 0; | 55 | unsigned long isa_io_base = 0; |
59 | unsigned long isa_mem_base = 0; | 56 | unsigned long isa_mem_base = 0; |
@@ -129,20 +126,21 @@ mpc834x_sys_setup_arch(void) | |||
129 | mdata->irq[1] = MPC83xx_IRQ_EXT2; | 126 | mdata->irq[1] = MPC83xx_IRQ_EXT2; |
130 | mdata->irq[2] = -1; | 127 | mdata->irq[2] = -1; |
131 | mdata->irq[31] = -1; | 128 | mdata->irq[31] = -1; |
132 | mdata->paddr += binfo->bi_immr_base; | ||
133 | 129 | ||
134 | /* setup the board related information for the enet controllers */ | 130 | /* setup the board related information for the enet controllers */ |
135 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1); | 131 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1); |
136 | if (pdata) { | 132 | if (pdata) { |
137 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | 133 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; |
138 | pdata->bus_id = GFAR_PHY_0; | 134 | pdata->bus_id = 0; |
135 | pdata->phy_id = 0; | ||
139 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); | 136 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); |
140 | } | 137 | } |
141 | 138 | ||
142 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2); | 139 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2); |
143 | if (pdata) { | 140 | if (pdata) { |
144 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | 141 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; |
145 | pdata->bus_id = GFAR_PHY_1; | 142 | pdata->bus_id = 0; |
143 | pdata->phy_id = 1; | ||
146 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); | 144 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); |
147 | } | 145 | } |
148 | 146 | ||
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c index c5cde97c6ef0..2eceb1e6f4eb 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.c +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c | |||
@@ -52,10 +52,6 @@ | |||
52 | 52 | ||
53 | #include <syslib/ppc85xx_setup.h> | 53 | #include <syslib/ppc85xx_setup.h> |
54 | 54 | ||
55 | static const char *GFAR_PHY_0 = "phy0:0"; | ||
56 | static const char *GFAR_PHY_1 = "phy0:1"; | ||
57 | static const char *GFAR_PHY_3 = "phy0:3"; | ||
58 | |||
59 | /* ************************************************************************ | 55 | /* ************************************************************************ |
60 | * | 56 | * |
61 | * Setup the architecture | 57 | * Setup the architecture |
@@ -102,27 +98,29 @@ mpc8540ads_setup_arch(void) | |||
102 | mdata->irq[2] = -1; | 98 | mdata->irq[2] = -1; |
103 | mdata->irq[3] = MPC85xx_IRQ_EXT5; | 99 | mdata->irq[3] = MPC85xx_IRQ_EXT5; |
104 | mdata->irq[31] = -1; | 100 | mdata->irq[31] = -1; |
105 | mdata->paddr += binfo->bi_immr_base; | ||
106 | 101 | ||
107 | /* setup the board related information for the enet controllers */ | 102 | /* setup the board related information for the enet controllers */ |
108 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | 103 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); |
109 | if (pdata) { | 104 | if (pdata) { |
110 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | 105 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; |
111 | pdata->bus_id = GFAR_PHY_0; | 106 | pdata->bus_id = 0; |
107 | pdata->phy_id = 0; | ||
112 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); | 108 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); |
113 | } | 109 | } |
114 | 110 | ||
115 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); | 111 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); |
116 | if (pdata) { | 112 | if (pdata) { |
117 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | 113 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; |
118 | pdata->bus_id = GFAR_PHY_1; | 114 | pdata->bus_id = 0; |
115 | pdata->phy_id = 1; | ||
119 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); | 116 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); |
120 | } | 117 | } |
121 | 118 | ||
122 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC); | 119 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC); |
123 | if (pdata) { | 120 | if (pdata) { |
124 | pdata->board_flags = 0; | 121 | pdata->board_flags = 0; |
125 | pdata->bus_id = GFAR_PHY_3; | 122 | pdata->bus_id = 0; |
123 | pdata->phy_id = 3; | ||
126 | memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6); | 124 | memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6); |
127 | } | 125 | } |
128 | 126 | ||
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c index 8e39a5517092..442c7ff195d3 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.c +++ b/arch/ppc/platforms/85xx/mpc8560_ads.c | |||
@@ -56,10 +56,6 @@ | |||
56 | #include <syslib/ppc85xx_setup.h> | 56 | #include <syslib/ppc85xx_setup.h> |
57 | 57 | ||
58 | 58 | ||
59 | static const char *GFAR_PHY_0 = "phy0:0"; | ||
60 | static const char *GFAR_PHY_1 = "phy0:1"; | ||
61 | static const char *GFAR_PHY_3 = "phy0:3"; | ||
62 | |||
63 | /* ************************************************************************ | 59 | /* ************************************************************************ |
64 | * | 60 | * |
65 | * Setup the architecture | 61 | * Setup the architecture |
@@ -99,20 +95,21 @@ mpc8560ads_setup_arch(void) | |||
99 | mdata->irq[2] = -1; | 95 | mdata->irq[2] = -1; |
100 | mdata->irq[3] = MPC85xx_IRQ_EXT5; | 96 | mdata->irq[3] = MPC85xx_IRQ_EXT5; |
101 | mdata->irq[31] = -1; | 97 | mdata->irq[31] = -1; |
102 | mdata->paddr += binfo->bi_immr_base; | ||
103 | 98 | ||
104 | /* setup the board related information for the enet controllers */ | 99 | /* setup the board related information for the enet controllers */ |
105 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | 100 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); |
106 | if (pdata) { | 101 | if (pdata) { |
107 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | 102 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; |
108 | pdata->bus_id = GFAR_PHY_0; | 103 | pdata->bus_id = 0; |
104 | pdata->phy_id = 0; | ||
109 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); | 105 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); |
110 | } | 106 | } |
111 | 107 | ||
112 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); | 108 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); |
113 | if (pdata) { | 109 | if (pdata) { |
114 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | 110 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; |
115 | pdata->bus_id = GFAR_PHY_1; | 111 | pdata->bus_id = 0; |
112 | pdata->phy_id = 1; | ||
116 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); | 113 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); |
117 | } | 114 | } |
118 | 115 | ||
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index 2959e3c4083d..b332ebae6bd3 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c | |||
@@ -395,9 +395,6 @@ mpc85xx_cds_pcibios_fixup(void) | |||
395 | 395 | ||
396 | TODC_ALLOC(); | 396 | TODC_ALLOC(); |
397 | 397 | ||
398 | static const char *GFAR_PHY_0 = "phy0:0"; | ||
399 | static const char *GFAR_PHY_1 = "phy0:1"; | ||
400 | |||
401 | /* ************************************************************************ | 398 | /* ************************************************************************ |
402 | * | 399 | * |
403 | * Setup the architecture | 400 | * Setup the architecture |
@@ -461,34 +458,37 @@ mpc85xx_cds_setup_arch(void) | |||
461 | mdata->irq[2] = -1; | 458 | mdata->irq[2] = -1; |
462 | mdata->irq[3] = -1; | 459 | mdata->irq[3] = -1; |
463 | mdata->irq[31] = -1; | 460 | mdata->irq[31] = -1; |
464 | mdata->paddr += binfo->bi_immr_base; | ||
465 | 461 | ||
466 | /* setup the board related information for the enet controllers */ | 462 | /* setup the board related information for the enet controllers */ |
467 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | 463 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); |
468 | if (pdata) { | 464 | if (pdata) { |
469 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | 465 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; |
470 | pdata->bus_id = GFAR_PHY_0; | 466 | pdata->bus_id = 0; |
467 | pdata->phy_id = 0; | ||
471 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); | 468 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); |
472 | } | 469 | } |
473 | 470 | ||
474 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); | 471 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); |
475 | if (pdata) { | 472 | if (pdata) { |
476 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | 473 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; |
477 | pdata->bus_id = GFAR_PHY_1; | 474 | pdata->bus_id = 0; |
475 | pdata->phy_id = 1; | ||
478 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); | 476 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); |
479 | } | 477 | } |
480 | 478 | ||
481 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC1); | 479 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC1); |
482 | if (pdata) { | 480 | if (pdata) { |
483 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | 481 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; |
484 | pdata->bus_id = GFAR_PHY_0; | 482 | pdata->bus_id = 0; |
483 | pdata->phy_id = 0; | ||
485 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); | 484 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); |
486 | } | 485 | } |
487 | 486 | ||
488 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC2); | 487 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC2); |
489 | if (pdata) { | 488 | if (pdata) { |
490 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | 489 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; |
491 | pdata->bus_id = GFAR_PHY_1; | 490 | pdata->bus_id = 0; |
491 | pdata->phy_id = 1; | ||
492 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); | 492 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); |
493 | } | 493 | } |
494 | 494 | ||
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index 45a5b81b4ed1..e777ba824aa9 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c | |||
@@ -91,9 +91,6 @@ sbc8560_early_serial_map(void) | |||
91 | } | 91 | } |
92 | #endif | 92 | #endif |
93 | 93 | ||
94 | static const char *GFAR_PHY_25 = "phy0:25"; | ||
95 | static const char *GFAR_PHY_26 = "phy0:26"; | ||
96 | |||
97 | /* ************************************************************************ | 94 | /* ************************************************************************ |
98 | * | 95 | * |
99 | * Setup the architecture | 96 | * Setup the architecture |
@@ -136,20 +133,21 @@ sbc8560_setup_arch(void) | |||
136 | mdata->irq[25] = MPC85xx_IRQ_EXT6; | 133 | mdata->irq[25] = MPC85xx_IRQ_EXT6; |
137 | mdata->irq[26] = MPC85xx_IRQ_EXT7; | 134 | mdata->irq[26] = MPC85xx_IRQ_EXT7; |
138 | mdata->irq[31] = -1; | 135 | mdata->irq[31] = -1; |
139 | mdata->paddr += binfo->bi_immr_base; | ||
140 | 136 | ||
141 | /* setup the board related information for the enet controllers */ | 137 | /* setup the board related information for the enet controllers */ |
142 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | 138 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); |
143 | if (pdata) { | 139 | if (pdata) { |
144 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | 140 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; |
145 | pdata->bus_id = GFAR_PHY_25; | 141 | pdata->bus_id = 0; |
142 | pdata->phy_id = 25; | ||
146 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); | 143 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); |
147 | } | 144 | } |
148 | 145 | ||
149 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); | 146 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); |
150 | if (pdata) { | 147 | if (pdata) { |
151 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | 148 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; |
152 | pdata->bus_id = GFAR_PHY_26; | 149 | pdata->bus_id = 0; |
150 | pdata->phy_id = 26; | ||
153 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); | 151 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); |
154 | } | 152 | } |
155 | 153 | ||
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c index 15ce9d070634..061bb7cf2d9a 100644 --- a/arch/ppc/platforms/85xx/stx_gp3.c +++ b/arch/ppc/platforms/85xx/stx_gp3.c | |||
@@ -93,9 +93,6 @@ static u8 gp3_openpic_initsenses[] __initdata = { | |||
93 | 0x0, /* External 11: */ | 93 | 0x0, /* External 11: */ |
94 | }; | 94 | }; |
95 | 95 | ||
96 | static const char *GFAR_PHY_2 = "phy0:2"; | ||
97 | static const char *GFAR_PHY_4 = "phy0:4"; | ||
98 | |||
99 | /* | 96 | /* |
100 | * Setup the architecture | 97 | * Setup the architecture |
101 | */ | 98 | */ |
@@ -130,20 +127,21 @@ gp3_setup_arch(void) | |||
130 | mdata->irq[2] = MPC85xx_IRQ_EXT5; | 127 | mdata->irq[2] = MPC85xx_IRQ_EXT5; |
131 | mdata->irq[4] = MPC85xx_IRQ_EXT5; | 128 | mdata->irq[4] = MPC85xx_IRQ_EXT5; |
132 | mdata->irq[31] = -1; | 129 | mdata->irq[31] = -1; |
133 | mdata->paddr += binfo->bi_immr_base; | ||
134 | 130 | ||
135 | /* setup the board related information for the enet controllers */ | 131 | /* setup the board related information for the enet controllers */ |
136 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | 132 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); |
137 | if (pdata) { | 133 | if (pdata) { |
138 | /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */ | 134 | /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */ |
139 | pdata->bus_id = GFAR_PHY_2; | 135 | pdata->bus_id = 0; |
136 | pdata->phy_id = 2; | ||
140 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); | 137 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); |
141 | } | 138 | } |
142 | 139 | ||
143 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); | 140 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); |
144 | if (pdata) { | 141 | if (pdata) { |
145 | /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */ | 142 | /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */ |
146 | pdata->bus_id = GFAR_PHY_4; | 143 | pdata->bus_id = 0; |
144 | pdata->phy_id = 4; | ||
147 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); | 145 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); |
148 | } | 146 | } |
149 | 147 | ||
diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c index c6dfd8f0f9df..b436f4d0a3fa 100644 --- a/arch/ppc/platforms/85xx/tqm85xx.c +++ b/arch/ppc/platforms/85xx/tqm85xx.c | |||
@@ -91,12 +91,6 @@ static u_char tqm85xx_openpic_initsenses[] __initdata = { | |||
91 | 0x0, /* External 11: */ | 91 | 0x0, /* External 11: */ |
92 | }; | 92 | }; |
93 | 93 | ||
94 | static const char *GFAR_PHY_0 = "phy0:2"; | ||
95 | static const char *GFAR_PHY_1 = "phy0:1"; | ||
96 | #ifdef CONFIG_MPC8540 | ||
97 | static const char *GFAR_PHY_3 = "phy0:3"; | ||
98 | #endif | ||
99 | |||
100 | /* ************************************************************************ | 94 | /* ************************************************************************ |
101 | * | 95 | * |
102 | * Setup the architecture | 96 | * Setup the architecture |
@@ -149,20 +143,21 @@ tqm85xx_setup_arch(void) | |||
149 | mdata->irq[2] = -1; | 143 | mdata->irq[2] = -1; |
150 | mdata->irq[3] = MPC85xx_IRQ_EXT8; | 144 | mdata->irq[3] = MPC85xx_IRQ_EXT8; |
151 | mdata->irq[31] = -1; | 145 | mdata->irq[31] = -1; |
152 | mdata->paddr += binfo->bi_immr_base; | ||
153 | 146 | ||
154 | /* setup the board related information for the enet controllers */ | 147 | /* setup the board related information for the enet controllers */ |
155 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | 148 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); |
156 | if (pdata) { | 149 | if (pdata) { |
157 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | 150 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; |
158 | pdata->bus_id = GFAR_PHY_0; | 151 | pdata->bus_id = 0; |
152 | pdata->phy_id = 2; | ||
159 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); | 153 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); |
160 | } | 154 | } |
161 | 155 | ||
162 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); | 156 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); |
163 | if (pdata) { | 157 | if (pdata) { |
164 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | 158 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; |
165 | pdata->bus_id = GFAR_PHY_1; | 159 | pdata->bus_id = 0; |
160 | pdata->phy_id = 1; | ||
166 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); | 161 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); |
167 | } | 162 | } |
168 | 163 | ||
@@ -170,7 +165,8 @@ tqm85xx_setup_arch(void) | |||
170 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC); | 165 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC); |
171 | if (pdata) { | 166 | if (pdata) { |
172 | pdata->board_flags = 0; | 167 | pdata->board_flags = 0; |
173 | pdata->bus_id = GFAR_PHY_3; | 168 | pdata->bus_id = 0; |
169 | pdata->phy_id = 3; | ||
174 | memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6); | 170 | memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6); |
175 | } | 171 | } |
176 | #endif | 172 | #endif |
diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index 847df4409982..f9b95de70e23 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c | |||
@@ -28,7 +28,6 @@ | |||
28 | */ | 28 | */ |
29 | 29 | ||
30 | struct gianfar_mdio_data mpc83xx_mdio_pdata = { | 30 | struct gianfar_mdio_data mpc83xx_mdio_pdata = { |
31 | .paddr = 0x24520, | ||
32 | }; | 31 | }; |
33 | 32 | ||
34 | static struct gianfar_platform_data mpc83xx_tsec1_pdata = { | 33 | static struct gianfar_platform_data mpc83xx_tsec1_pdata = { |
@@ -226,7 +225,14 @@ struct platform_device ppc_sys_platform_devices[] = { | |||
226 | .name = "fsl-gianfar_mdio", | 225 | .name = "fsl-gianfar_mdio", |
227 | .id = 0, | 226 | .id = 0, |
228 | .dev.platform_data = &mpc83xx_mdio_pdata, | 227 | .dev.platform_data = &mpc83xx_mdio_pdata, |
229 | .num_resources = 0, | 228 | .num_resources = 1, |
229 | .resource = (struct resource[]) { | ||
230 | { | ||
231 | .start = 0x24520, | ||
232 | .end = 0x2453f, | ||
233 | .flags = IORESOURCE_MEM, | ||
234 | }, | ||
235 | }, | ||
230 | }, | 236 | }, |
231 | }; | 237 | }; |
232 | 238 | ||
diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c index 69949d255658..00e9b6ff2f6e 100644 --- a/arch/ppc/syslib/mpc85xx_devices.c +++ b/arch/ppc/syslib/mpc85xx_devices.c | |||
@@ -26,7 +26,6 @@ | |||
26 | * what CCSRBAR is, will get fixed up by mach_mpc85xx_fixup | 26 | * what CCSRBAR is, will get fixed up by mach_mpc85xx_fixup |
27 | */ | 27 | */ |
28 | struct gianfar_mdio_data mpc85xx_mdio_pdata = { | 28 | struct gianfar_mdio_data mpc85xx_mdio_pdata = { |
29 | .paddr = MPC85xx_MIIM_OFFSET, | ||
30 | }; | 29 | }; |
31 | 30 | ||
32 | static struct gianfar_platform_data mpc85xx_tsec1_pdata = { | 31 | static struct gianfar_platform_data mpc85xx_tsec1_pdata = { |
@@ -720,7 +719,14 @@ struct platform_device ppc_sys_platform_devices[] = { | |||
720 | .name = "fsl-gianfar_mdio", | 719 | .name = "fsl-gianfar_mdio", |
721 | .id = 0, | 720 | .id = 0, |
722 | .dev.platform_data = &mpc85xx_mdio_pdata, | 721 | .dev.platform_data = &mpc85xx_mdio_pdata, |
723 | .num_resources = 0, | 722 | .num_resources = 1, |
723 | .resource = (struct resource[]) { | ||
724 | { | ||
725 | .start = 0x24520, | ||
726 | .end = 0x2453f, | ||
727 | .flags = IORESOURCE_MEM, | ||
728 | }, | ||
729 | }, | ||
724 | }, | 730 | }, |
725 | }; | 731 | }; |
726 | 732 | ||
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 667a21c72edb..7ac365b5d9ec 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -129,7 +129,6 @@ static struct serial_state rs_table[1]; | |||
129 | * memory if large numbers of serial ports are open. | 129 | * memory if large numbers of serial ports are open. |
130 | */ | 130 | */ |
131 | static unsigned char *tmp_buf; | 131 | static unsigned char *tmp_buf; |
132 | static DECLARE_MUTEX(tmp_buf_sem); | ||
133 | 132 | ||
134 | #include <asm/uaccess.h> | 133 | #include <asm/uaccess.h> |
135 | 134 | ||
diff --git a/drivers/char/esp.c b/drivers/char/esp.c index e469f641c728..dd5dc8fa490d 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c | |||
@@ -160,7 +160,6 @@ static void rs_wait_until_sent(struct tty_struct *, int); | |||
160 | * memory if large numbers of serial ports are open. | 160 | * memory if large numbers of serial ports are open. |
161 | */ | 161 | */ |
162 | static unsigned char *tmp_buf; | 162 | static unsigned char *tmp_buf; |
163 | static DECLARE_MUTEX(tmp_buf_sem); | ||
164 | 163 | ||
165 | static inline int serial_paranoia_check(struct esp_struct *info, | 164 | static inline int serial_paranoia_check(struct esp_struct *info, |
166 | char *name, const char *routine) | 165 | char *name, const char *routine) |
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 204a7302a4a9..e38a5f0e07bb 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #define DEBUG | 34 | #define DEBUG |
35 | 35 | ||
36 | static char * tmp_buf; | 36 | static char * tmp_buf; |
37 | static DECLARE_MUTEX(tmp_buf_sem); | ||
38 | 37 | ||
39 | static int gs_debug; | 38 | static int gs_debug; |
40 | 39 | ||
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 050e70ee5920..119e629656b7 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -82,7 +82,6 @@ | |||
82 | static struct riscom_board * IRQ_to_board[16]; | 82 | static struct riscom_board * IRQ_to_board[16]; |
83 | static struct tty_driver *riscom_driver; | 83 | static struct tty_driver *riscom_driver; |
84 | static unsigned char * tmp_buf; | 84 | static unsigned char * tmp_buf; |
85 | static DECLARE_MUTEX(tmp_buf_sem); | ||
86 | 85 | ||
87 | static unsigned long baud_table[] = { | 86 | static unsigned long baud_table[] = { |
88 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, | 87 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, |
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index f36342ae8e7e..037c940ac71b 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c | |||
@@ -129,7 +129,6 @@ struct cyclades_port cy_port[] = { | |||
129 | * memory if large numbers of serial ports are open. | 129 | * memory if large numbers of serial ports are open. |
130 | */ | 130 | */ |
131 | static unsigned char *tmp_buf = 0; | 131 | static unsigned char *tmp_buf = 0; |
132 | DECLARE_MUTEX(tmp_buf_sem); | ||
133 | 132 | ||
134 | /* | 133 | /* |
135 | * This is used to look up the divisor speeds and the timeouts | 134 | * This is used to look up the divisor speeds and the timeouts |
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 0a574bdbce36..5343e9fc6ab7 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
@@ -184,7 +184,6 @@ static int sx_poll = HZ; | |||
184 | 184 | ||
185 | static struct tty_driver *specialix_driver; | 185 | static struct tty_driver *specialix_driver; |
186 | static unsigned char * tmp_buf; | 186 | static unsigned char * tmp_buf; |
187 | static DECLARE_MUTEX(tmp_buf_sem); | ||
188 | 187 | ||
189 | static unsigned long baud_table[] = { | 188 | static unsigned long baud_table[] = { |
190 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, | 189 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, |
@@ -2556,8 +2555,6 @@ static int __init specialix_init_module(void) | |||
2556 | 2555 | ||
2557 | func_enter(); | 2556 | func_enter(); |
2558 | 2557 | ||
2559 | init_MUTEX(&tmp_buf_sem); /* Init de the semaphore - pvdl */ | ||
2560 | |||
2561 | if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { | 2558 | if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { |
2562 | for(i = 0; i < SX_NBOARD; i++) { | 2559 | for(i = 0; i < SX_NBOARD; i++) { |
2563 | sx_board[i].base = iobase[i]; | 2560 | sx_board[i].base = iobase[i]; |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 9f1b466c4f84..ede688a4e141 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -951,7 +951,6 @@ static void* mgsl_get_text_ptr(void) | |||
951 | * memory if large numbers of serial ports are open. | 951 | * memory if large numbers of serial ports are open. |
952 | */ | 952 | */ |
953 | static unsigned char *tmp_buf; | 953 | static unsigned char *tmp_buf; |
954 | static DECLARE_MUTEX(tmp_buf_sem); | ||
955 | 954 | ||
956 | static inline int mgsl_paranoia_check(struct mgsl_struct *info, | 955 | static inline int mgsl_paranoia_check(struct mgsl_struct *info, |
957 | char *name, const char *routine) | 956 | char *name, const char *routine) |
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 3a611fe5497e..c06b18102b6a 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
@@ -3163,22 +3163,6 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id, | |||
3163 | } | 3163 | } |
3164 | EXPORT_SYMBOL(ib_cm_init_qp_attr); | 3164 | EXPORT_SYMBOL(ib_cm_init_qp_attr); |
3165 | 3165 | ||
3166 | static __be64 cm_get_ca_guid(struct ib_device *device) | ||
3167 | { | ||
3168 | struct ib_device_attr *device_attr; | ||
3169 | __be64 guid; | ||
3170 | int ret; | ||
3171 | |||
3172 | device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL); | ||
3173 | if (!device_attr) | ||
3174 | return 0; | ||
3175 | |||
3176 | ret = ib_query_device(device, device_attr); | ||
3177 | guid = ret ? 0 : device_attr->node_guid; | ||
3178 | kfree(device_attr); | ||
3179 | return guid; | ||
3180 | } | ||
3181 | |||
3182 | static void cm_add_one(struct ib_device *device) | 3166 | static void cm_add_one(struct ib_device *device) |
3183 | { | 3167 | { |
3184 | struct cm_device *cm_dev; | 3168 | struct cm_device *cm_dev; |
@@ -3200,9 +3184,7 @@ static void cm_add_one(struct ib_device *device) | |||
3200 | return; | 3184 | return; |
3201 | 3185 | ||
3202 | cm_dev->device = device; | 3186 | cm_dev->device = device; |
3203 | cm_dev->ca_guid = cm_get_ca_guid(device); | 3187 | cm_dev->ca_guid = device->node_guid; |
3204 | if (!cm_dev->ca_guid) | ||
3205 | goto error1; | ||
3206 | 3188 | ||
3207 | set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask); | 3189 | set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask); |
3208 | for (i = 1; i <= device->phys_port_cnt; i++) { | 3190 | for (i = 1; i <= device->phys_port_cnt; i++) { |
@@ -3217,11 +3199,11 @@ static void cm_add_one(struct ib_device *device) | |||
3217 | cm_recv_handler, | 3199 | cm_recv_handler, |
3218 | port); | 3200 | port); |
3219 | if (IS_ERR(port->mad_agent)) | 3201 | if (IS_ERR(port->mad_agent)) |
3220 | goto error2; | 3202 | goto error1; |
3221 | 3203 | ||
3222 | ret = ib_modify_port(device, i, 0, &port_modify); | 3204 | ret = ib_modify_port(device, i, 0, &port_modify); |
3223 | if (ret) | 3205 | if (ret) |
3224 | goto error3; | 3206 | goto error2; |
3225 | } | 3207 | } |
3226 | ib_set_client_data(device, &cm_client, cm_dev); | 3208 | ib_set_client_data(device, &cm_client, cm_dev); |
3227 | 3209 | ||
@@ -3230,9 +3212,9 @@ static void cm_add_one(struct ib_device *device) | |||
3230 | write_unlock_irqrestore(&cm.device_lock, flags); | 3212 | write_unlock_irqrestore(&cm.device_lock, flags); |
3231 | return; | 3213 | return; |
3232 | 3214 | ||
3233 | error3: | ||
3234 | ib_unregister_mad_agent(port->mad_agent); | ||
3235 | error2: | 3215 | error2: |
3216 | ib_unregister_mad_agent(port->mad_agent); | ||
3217 | error1: | ||
3236 | port_modify.set_port_cap_mask = 0; | 3218 | port_modify.set_port_cap_mask = 0; |
3237 | port_modify.clr_port_cap_mask = IB_PORT_CM_SUP; | 3219 | port_modify.clr_port_cap_mask = IB_PORT_CM_SUP; |
3238 | while (--i) { | 3220 | while (--i) { |
@@ -3240,7 +3222,6 @@ error2: | |||
3240 | ib_modify_port(device, port->port_num, 0, &port_modify); | 3222 | ib_modify_port(device, port->port_num, 0, &port_modify); |
3241 | ib_unregister_mad_agent(port->mad_agent); | 3223 | ib_unregister_mad_agent(port->mad_agent); |
3242 | } | 3224 | } |
3243 | error1: | ||
3244 | kfree(cm_dev); | 3225 | kfree(cm_dev); |
3245 | } | 3226 | } |
3246 | 3227 | ||
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index e169e798354b..b2f3cb91d9bc 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c | |||
@@ -38,8 +38,7 @@ | |||
38 | #include <linux/errno.h> | 38 | #include <linux/errno.h> |
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
41 | 41 | #include <linux/mutex.h> | |
42 | #include <asm/semaphore.h> | ||
43 | 42 | ||
44 | #include "core_priv.h" | 43 | #include "core_priv.h" |
45 | 44 | ||
@@ -57,13 +56,13 @@ static LIST_HEAD(device_list); | |||
57 | static LIST_HEAD(client_list); | 56 | static LIST_HEAD(client_list); |
58 | 57 | ||
59 | /* | 58 | /* |
60 | * device_sem protects access to both device_list and client_list. | 59 | * device_mutex protects access to both device_list and client_list. |
61 | * There's no real point to using multiple locks or something fancier | 60 | * There's no real point to using multiple locks or something fancier |
62 | * like an rwsem: we always access both lists, and we're always | 61 | * like an rwsem: we always access both lists, and we're always |
63 | * modifying one list or the other list. In any case this is not a | 62 | * modifying one list or the other list. In any case this is not a |
64 | * hot path so there's no point in trying to optimize. | 63 | * hot path so there's no point in trying to optimize. |
65 | */ | 64 | */ |
66 | static DECLARE_MUTEX(device_sem); | 65 | static DEFINE_MUTEX(device_mutex); |
67 | 66 | ||
68 | static int ib_device_check_mandatory(struct ib_device *device) | 67 | static int ib_device_check_mandatory(struct ib_device *device) |
69 | { | 68 | { |
@@ -221,7 +220,7 @@ int ib_register_device(struct ib_device *device) | |||
221 | { | 220 | { |
222 | int ret; | 221 | int ret; |
223 | 222 | ||
224 | down(&device_sem); | 223 | mutex_lock(&device_mutex); |
225 | 224 | ||
226 | if (strchr(device->name, '%')) { | 225 | if (strchr(device->name, '%')) { |
227 | ret = alloc_name(device->name); | 226 | ret = alloc_name(device->name); |
@@ -259,7 +258,7 @@ int ib_register_device(struct ib_device *device) | |||
259 | } | 258 | } |
260 | 259 | ||
261 | out: | 260 | out: |
262 | up(&device_sem); | 261 | mutex_unlock(&device_mutex); |
263 | return ret; | 262 | return ret; |
264 | } | 263 | } |
265 | EXPORT_SYMBOL(ib_register_device); | 264 | EXPORT_SYMBOL(ib_register_device); |
@@ -276,7 +275,7 @@ void ib_unregister_device(struct ib_device *device) | |||
276 | struct ib_client_data *context, *tmp; | 275 | struct ib_client_data *context, *tmp; |
277 | unsigned long flags; | 276 | unsigned long flags; |
278 | 277 | ||
279 | down(&device_sem); | 278 | mutex_lock(&device_mutex); |
280 | 279 | ||
281 | list_for_each_entry_reverse(client, &client_list, list) | 280 | list_for_each_entry_reverse(client, &client_list, list) |
282 | if (client->remove) | 281 | if (client->remove) |
@@ -284,7 +283,7 @@ void ib_unregister_device(struct ib_device *device) | |||
284 | 283 | ||
285 | list_del(&device->core_list); | 284 | list_del(&device->core_list); |
286 | 285 | ||
287 | up(&device_sem); | 286 | mutex_unlock(&device_mutex); |
288 | 287 | ||
289 | spin_lock_irqsave(&device->client_data_lock, flags); | 288 | spin_lock_irqsave(&device->client_data_lock, flags); |
290 | list_for_each_entry_safe(context, tmp, &device->client_data_list, list) | 289 | list_for_each_entry_safe(context, tmp, &device->client_data_list, list) |
@@ -312,14 +311,14 @@ int ib_register_client(struct ib_client *client) | |||
312 | { | 311 | { |
313 | struct ib_device *device; | 312 | struct ib_device *device; |
314 | 313 | ||
315 | down(&device_sem); | 314 | mutex_lock(&device_mutex); |
316 | 315 | ||
317 | list_add_tail(&client->list, &client_list); | 316 | list_add_tail(&client->list, &client_list); |
318 | list_for_each_entry(device, &device_list, core_list) | 317 | list_for_each_entry(device, &device_list, core_list) |
319 | if (client->add && !add_client_context(device, client)) | 318 | if (client->add && !add_client_context(device, client)) |
320 | client->add(device); | 319 | client->add(device); |
321 | 320 | ||
322 | up(&device_sem); | 321 | mutex_unlock(&device_mutex); |
323 | 322 | ||
324 | return 0; | 323 | return 0; |
325 | } | 324 | } |
@@ -339,7 +338,7 @@ void ib_unregister_client(struct ib_client *client) | |||
339 | struct ib_device *device; | 338 | struct ib_device *device; |
340 | unsigned long flags; | 339 | unsigned long flags; |
341 | 340 | ||
342 | down(&device_sem); | 341 | mutex_lock(&device_mutex); |
343 | 342 | ||
344 | list_for_each_entry(device, &device_list, core_list) { | 343 | list_for_each_entry(device, &device_list, core_list) { |
345 | if (client->remove) | 344 | if (client->remove) |
@@ -355,7 +354,7 @@ void ib_unregister_client(struct ib_client *client) | |||
355 | } | 354 | } |
356 | list_del(&client->list); | 355 | list_del(&client->list); |
357 | 356 | ||
358 | up(&device_sem); | 357 | mutex_unlock(&device_mutex); |
359 | } | 358 | } |
360 | EXPORT_SYMBOL(ib_unregister_client); | 359 | EXPORT_SYMBOL(ib_unregister_client); |
361 | 360 | ||
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 1f1743c5c9a3..5982d687a000 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c | |||
@@ -445,13 +445,7 @@ static int ib_device_uevent(struct class_device *cdev, char **envp, | |||
445 | return -ENOMEM; | 445 | return -ENOMEM; |
446 | 446 | ||
447 | /* | 447 | /* |
448 | * It might be nice to pass the node GUID with the event, but | 448 | * It would be nice to pass the node GUID with the event... |
449 | * right now the only way to get it is to query the device | ||
450 | * provider, and this can crash during device removal because | ||
451 | * we are will be running after driver removal has started. | ||
452 | * We could add a node_guid field to struct ib_device, or we | ||
453 | * could just let userspace read the node GUID from sysfs when | ||
454 | * devices are added. | ||
455 | */ | 449 | */ |
456 | 450 | ||
457 | envp[i] = NULL; | 451 | envp[i] = NULL; |
@@ -623,21 +617,15 @@ static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf) | |||
623 | static ssize_t show_node_guid(struct class_device *cdev, char *buf) | 617 | static ssize_t show_node_guid(struct class_device *cdev, char *buf) |
624 | { | 618 | { |
625 | struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); | 619 | struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); |
626 | struct ib_device_attr attr; | ||
627 | ssize_t ret; | ||
628 | 620 | ||
629 | if (!ibdev_is_alive(dev)) | 621 | if (!ibdev_is_alive(dev)) |
630 | return -ENODEV; | 622 | return -ENODEV; |
631 | 623 | ||
632 | ret = ib_query_device(dev, &attr); | ||
633 | if (ret) | ||
634 | return ret; | ||
635 | |||
636 | return sprintf(buf, "%04x:%04x:%04x:%04x\n", | 624 | return sprintf(buf, "%04x:%04x:%04x:%04x\n", |
637 | be16_to_cpu(((__be16 *) &attr.node_guid)[0]), | 625 | be16_to_cpu(((__be16 *) &dev->node_guid)[0]), |
638 | be16_to_cpu(((__be16 *) &attr.node_guid)[1]), | 626 | be16_to_cpu(((__be16 *) &dev->node_guid)[1]), |
639 | be16_to_cpu(((__be16 *) &attr.node_guid)[2]), | 627 | be16_to_cpu(((__be16 *) &dev->node_guid)[2]), |
640 | be16_to_cpu(((__be16 *) &attr.node_guid)[3])); | 628 | be16_to_cpu(((__be16 *) &dev->node_guid)[3])); |
641 | } | 629 | } |
642 | 630 | ||
643 | static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL); | 631 | static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL); |
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 6e15787d1de1..e95c4293a496 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/mount.h> | 42 | #include <linux/mount.h> |
43 | #include <linux/cdev.h> | 43 | #include <linux/cdev.h> |
44 | #include <linux/idr.h> | 44 | #include <linux/idr.h> |
45 | #include <linux/mutex.h> | ||
45 | 46 | ||
46 | #include <asm/uaccess.h> | 47 | #include <asm/uaccess.h> |
47 | 48 | ||
@@ -113,7 +114,7 @@ static struct ib_client ucm_client = { | |||
113 | .remove = ib_ucm_remove_one | 114 | .remove = ib_ucm_remove_one |
114 | }; | 115 | }; |
115 | 116 | ||
116 | static DECLARE_MUTEX(ctx_id_mutex); | 117 | static DEFINE_MUTEX(ctx_id_mutex); |
117 | static DEFINE_IDR(ctx_id_table); | 118 | static DEFINE_IDR(ctx_id_table); |
118 | static DECLARE_BITMAP(dev_map, IB_UCM_MAX_DEVICES); | 119 | static DECLARE_BITMAP(dev_map, IB_UCM_MAX_DEVICES); |
119 | 120 | ||
@@ -121,7 +122,7 @@ static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id) | |||
121 | { | 122 | { |
122 | struct ib_ucm_context *ctx; | 123 | struct ib_ucm_context *ctx; |
123 | 124 | ||
124 | down(&ctx_id_mutex); | 125 | mutex_lock(&ctx_id_mutex); |
125 | ctx = idr_find(&ctx_id_table, id); | 126 | ctx = idr_find(&ctx_id_table, id); |
126 | if (!ctx) | 127 | if (!ctx) |
127 | ctx = ERR_PTR(-ENOENT); | 128 | ctx = ERR_PTR(-ENOENT); |
@@ -129,7 +130,7 @@ static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id) | |||
129 | ctx = ERR_PTR(-EINVAL); | 130 | ctx = ERR_PTR(-EINVAL); |
130 | else | 131 | else |
131 | atomic_inc(&ctx->ref); | 132 | atomic_inc(&ctx->ref); |
132 | up(&ctx_id_mutex); | 133 | mutex_unlock(&ctx_id_mutex); |
133 | 134 | ||
134 | return ctx; | 135 | return ctx; |
135 | } | 136 | } |
@@ -186,9 +187,9 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file) | |||
186 | if (!result) | 187 | if (!result) |
187 | goto error; | 188 | goto error; |
188 | 189 | ||
189 | down(&ctx_id_mutex); | 190 | mutex_lock(&ctx_id_mutex); |
190 | result = idr_get_new(&ctx_id_table, ctx, &ctx->id); | 191 | result = idr_get_new(&ctx_id_table, ctx, &ctx->id); |
191 | up(&ctx_id_mutex); | 192 | mutex_unlock(&ctx_id_mutex); |
192 | } while (result == -EAGAIN); | 193 | } while (result == -EAGAIN); |
193 | 194 | ||
194 | if (result) | 195 | if (result) |
@@ -550,9 +551,9 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file, | |||
550 | err2: | 551 | err2: |
551 | ib_destroy_cm_id(ctx->cm_id); | 552 | ib_destroy_cm_id(ctx->cm_id); |
552 | err1: | 553 | err1: |
553 | down(&ctx_id_mutex); | 554 | mutex_lock(&ctx_id_mutex); |
554 | idr_remove(&ctx_id_table, ctx->id); | 555 | idr_remove(&ctx_id_table, ctx->id); |
555 | up(&ctx_id_mutex); | 556 | mutex_unlock(&ctx_id_mutex); |
556 | kfree(ctx); | 557 | kfree(ctx); |
557 | return result; | 558 | return result; |
558 | } | 559 | } |
@@ -572,7 +573,7 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file, | |||
572 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) | 573 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) |
573 | return -EFAULT; | 574 | return -EFAULT; |
574 | 575 | ||
575 | down(&ctx_id_mutex); | 576 | mutex_lock(&ctx_id_mutex); |
576 | ctx = idr_find(&ctx_id_table, cmd.id); | 577 | ctx = idr_find(&ctx_id_table, cmd.id); |
577 | if (!ctx) | 578 | if (!ctx) |
578 | ctx = ERR_PTR(-ENOENT); | 579 | ctx = ERR_PTR(-ENOENT); |
@@ -580,7 +581,7 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file, | |||
580 | ctx = ERR_PTR(-EINVAL); | 581 | ctx = ERR_PTR(-EINVAL); |
581 | else | 582 | else |
582 | idr_remove(&ctx_id_table, ctx->id); | 583 | idr_remove(&ctx_id_table, ctx->id); |
583 | up(&ctx_id_mutex); | 584 | mutex_unlock(&ctx_id_mutex); |
584 | 585 | ||
585 | if (IS_ERR(ctx)) | 586 | if (IS_ERR(ctx)) |
586 | return PTR_ERR(ctx); | 587 | return PTR_ERR(ctx); |
@@ -1280,9 +1281,9 @@ static int ib_ucm_close(struct inode *inode, struct file *filp) | |||
1280 | struct ib_ucm_context, file_list); | 1281 | struct ib_ucm_context, file_list); |
1281 | up(&file->mutex); | 1282 | up(&file->mutex); |
1282 | 1283 | ||
1283 | down(&ctx_id_mutex); | 1284 | mutex_lock(&ctx_id_mutex); |
1284 | idr_remove(&ctx_id_table, ctx->id); | 1285 | idr_remove(&ctx_id_table, ctx->id); |
1285 | up(&ctx_id_mutex); | 1286 | mutex_unlock(&ctx_id_mutex); |
1286 | 1287 | ||
1287 | ib_destroy_cm_id(ctx->cm_id); | 1288 | ib_destroy_cm_id(ctx->cm_id); |
1288 | ib_ucm_cleanup_events(ctx); | 1289 | ib_ucm_cleanup_events(ctx); |
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index 7114e3fbab00..f7eecbc6af6c 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h | |||
@@ -41,6 +41,7 @@ | |||
41 | 41 | ||
42 | #include <linux/kref.h> | 42 | #include <linux/kref.h> |
43 | #include <linux/idr.h> | 43 | #include <linux/idr.h> |
44 | #include <linux/mutex.h> | ||
44 | 45 | ||
45 | #include <rdma/ib_verbs.h> | 46 | #include <rdma/ib_verbs.h> |
46 | #include <rdma/ib_user_verbs.h> | 47 | #include <rdma/ib_user_verbs.h> |
@@ -88,7 +89,7 @@ struct ib_uverbs_event_file { | |||
88 | 89 | ||
89 | struct ib_uverbs_file { | 90 | struct ib_uverbs_file { |
90 | struct kref ref; | 91 | struct kref ref; |
91 | struct semaphore mutex; | 92 | struct mutex mutex; |
92 | struct ib_uverbs_device *device; | 93 | struct ib_uverbs_device *device; |
93 | struct ib_ucontext *ucontext; | 94 | struct ib_ucontext *ucontext; |
94 | struct ib_event_handler event_handler; | 95 | struct ib_event_handler event_handler; |
@@ -131,7 +132,7 @@ struct ib_ucq_object { | |||
131 | u32 async_events_reported; | 132 | u32 async_events_reported; |
132 | }; | 133 | }; |
133 | 134 | ||
134 | extern struct semaphore ib_uverbs_idr_mutex; | 135 | extern struct mutex ib_uverbs_idr_mutex; |
135 | extern struct idr ib_uverbs_pd_idr; | 136 | extern struct idr ib_uverbs_pd_idr; |
136 | extern struct idr ib_uverbs_mr_idr; | 137 | extern struct idr ib_uverbs_mr_idr; |
137 | extern struct idr ib_uverbs_mw_idr; | 138 | extern struct idr ib_uverbs_mw_idr; |
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index a02c5a05c984..407b6284d7d5 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
@@ -67,7 +67,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, | |||
67 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 67 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
68 | return -EFAULT; | 68 | return -EFAULT; |
69 | 69 | ||
70 | down(&file->mutex); | 70 | mutex_lock(&file->mutex); |
71 | 71 | ||
72 | if (file->ucontext) { | 72 | if (file->ucontext) { |
73 | ret = -EINVAL; | 73 | ret = -EINVAL; |
@@ -119,7 +119,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, | |||
119 | 119 | ||
120 | fd_install(resp.async_fd, filp); | 120 | fd_install(resp.async_fd, filp); |
121 | 121 | ||
122 | up(&file->mutex); | 122 | mutex_unlock(&file->mutex); |
123 | 123 | ||
124 | return in_len; | 124 | return in_len; |
125 | 125 | ||
@@ -131,7 +131,7 @@ err_free: | |||
131 | ibdev->dealloc_ucontext(ucontext); | 131 | ibdev->dealloc_ucontext(ucontext); |
132 | 132 | ||
133 | err: | 133 | err: |
134 | up(&file->mutex); | 134 | mutex_unlock(&file->mutex); |
135 | return ret; | 135 | return ret; |
136 | } | 136 | } |
137 | 137 | ||
@@ -157,7 +157,7 @@ ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file, | |||
157 | memset(&resp, 0, sizeof resp); | 157 | memset(&resp, 0, sizeof resp); |
158 | 158 | ||
159 | resp.fw_ver = attr.fw_ver; | 159 | resp.fw_ver = attr.fw_ver; |
160 | resp.node_guid = attr.node_guid; | 160 | resp.node_guid = file->device->ib_dev->node_guid; |
161 | resp.sys_image_guid = attr.sys_image_guid; | 161 | resp.sys_image_guid = attr.sys_image_guid; |
162 | resp.max_mr_size = attr.max_mr_size; | 162 | resp.max_mr_size = attr.max_mr_size; |
163 | resp.page_size_cap = attr.page_size_cap; | 163 | resp.page_size_cap = attr.page_size_cap; |
@@ -290,7 +290,7 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file, | |||
290 | pd->uobject = uobj; | 290 | pd->uobject = uobj; |
291 | atomic_set(&pd->usecnt, 0); | 291 | atomic_set(&pd->usecnt, 0); |
292 | 292 | ||
293 | down(&ib_uverbs_idr_mutex); | 293 | mutex_lock(&ib_uverbs_idr_mutex); |
294 | 294 | ||
295 | retry: | 295 | retry: |
296 | if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) { | 296 | if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) { |
@@ -314,11 +314,11 @@ retry: | |||
314 | goto err_idr; | 314 | goto err_idr; |
315 | } | 315 | } |
316 | 316 | ||
317 | down(&file->mutex); | 317 | mutex_lock(&file->mutex); |
318 | list_add_tail(&uobj->list, &file->ucontext->pd_list); | 318 | list_add_tail(&uobj->list, &file->ucontext->pd_list); |
319 | up(&file->mutex); | 319 | mutex_unlock(&file->mutex); |
320 | 320 | ||
321 | up(&ib_uverbs_idr_mutex); | 321 | mutex_unlock(&ib_uverbs_idr_mutex); |
322 | 322 | ||
323 | return in_len; | 323 | return in_len; |
324 | 324 | ||
@@ -326,7 +326,7 @@ err_idr: | |||
326 | idr_remove(&ib_uverbs_pd_idr, uobj->id); | 326 | idr_remove(&ib_uverbs_pd_idr, uobj->id); |
327 | 327 | ||
328 | err_up: | 328 | err_up: |
329 | up(&ib_uverbs_idr_mutex); | 329 | mutex_unlock(&ib_uverbs_idr_mutex); |
330 | ib_dealloc_pd(pd); | 330 | ib_dealloc_pd(pd); |
331 | 331 | ||
332 | err: | 332 | err: |
@@ -346,7 +346,7 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file, | |||
346 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 346 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
347 | return -EFAULT; | 347 | return -EFAULT; |
348 | 348 | ||
349 | down(&ib_uverbs_idr_mutex); | 349 | mutex_lock(&ib_uverbs_idr_mutex); |
350 | 350 | ||
351 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); | 351 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); |
352 | if (!pd || pd->uobject->context != file->ucontext) | 352 | if (!pd || pd->uobject->context != file->ucontext) |
@@ -360,14 +360,14 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file, | |||
360 | 360 | ||
361 | idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); | 361 | idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); |
362 | 362 | ||
363 | down(&file->mutex); | 363 | mutex_lock(&file->mutex); |
364 | list_del(&uobj->list); | 364 | list_del(&uobj->list); |
365 | up(&file->mutex); | 365 | mutex_unlock(&file->mutex); |
366 | 366 | ||
367 | kfree(uobj); | 367 | kfree(uobj); |
368 | 368 | ||
369 | out: | 369 | out: |
370 | up(&ib_uverbs_idr_mutex); | 370 | mutex_unlock(&ib_uverbs_idr_mutex); |
371 | 371 | ||
372 | return ret ? ret : in_len; | 372 | return ret ? ret : in_len; |
373 | } | 373 | } |
@@ -426,7 +426,7 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, | |||
426 | 426 | ||
427 | obj->umem.virt_base = cmd.hca_va; | 427 | obj->umem.virt_base = cmd.hca_va; |
428 | 428 | ||
429 | down(&ib_uverbs_idr_mutex); | 429 | mutex_lock(&ib_uverbs_idr_mutex); |
430 | 430 | ||
431 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); | 431 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); |
432 | if (!pd || pd->uobject->context != file->ucontext) { | 432 | if (!pd || pd->uobject->context != file->ucontext) { |
@@ -476,11 +476,11 @@ retry: | |||
476 | goto err_idr; | 476 | goto err_idr; |
477 | } | 477 | } |
478 | 478 | ||
479 | down(&file->mutex); | 479 | mutex_lock(&file->mutex); |
480 | list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); | 480 | list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); |
481 | up(&file->mutex); | 481 | mutex_unlock(&file->mutex); |
482 | 482 | ||
483 | up(&ib_uverbs_idr_mutex); | 483 | mutex_unlock(&ib_uverbs_idr_mutex); |
484 | 484 | ||
485 | return in_len; | 485 | return in_len; |
486 | 486 | ||
@@ -492,7 +492,7 @@ err_unreg: | |||
492 | atomic_dec(&pd->usecnt); | 492 | atomic_dec(&pd->usecnt); |
493 | 493 | ||
494 | err_up: | 494 | err_up: |
495 | up(&ib_uverbs_idr_mutex); | 495 | mutex_unlock(&ib_uverbs_idr_mutex); |
496 | 496 | ||
497 | ib_umem_release(file->device->ib_dev, &obj->umem); | 497 | ib_umem_release(file->device->ib_dev, &obj->umem); |
498 | 498 | ||
@@ -513,7 +513,7 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, | |||
513 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 513 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
514 | return -EFAULT; | 514 | return -EFAULT; |
515 | 515 | ||
516 | down(&ib_uverbs_idr_mutex); | 516 | mutex_lock(&ib_uverbs_idr_mutex); |
517 | 517 | ||
518 | mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle); | 518 | mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle); |
519 | if (!mr || mr->uobject->context != file->ucontext) | 519 | if (!mr || mr->uobject->context != file->ucontext) |
@@ -527,15 +527,15 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, | |||
527 | 527 | ||
528 | idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); | 528 | idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); |
529 | 529 | ||
530 | down(&file->mutex); | 530 | mutex_lock(&file->mutex); |
531 | list_del(&memobj->uobject.list); | 531 | list_del(&memobj->uobject.list); |
532 | up(&file->mutex); | 532 | mutex_unlock(&file->mutex); |
533 | 533 | ||
534 | ib_umem_release(file->device->ib_dev, &memobj->umem); | 534 | ib_umem_release(file->device->ib_dev, &memobj->umem); |
535 | kfree(memobj); | 535 | kfree(memobj); |
536 | 536 | ||
537 | out: | 537 | out: |
538 | up(&ib_uverbs_idr_mutex); | 538 | mutex_unlock(&ib_uverbs_idr_mutex); |
539 | 539 | ||
540 | return ret ? ret : in_len; | 540 | return ret ? ret : in_len; |
541 | } | 541 | } |
@@ -628,7 +628,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, | |||
628 | cq->cq_context = ev_file; | 628 | cq->cq_context = ev_file; |
629 | atomic_set(&cq->usecnt, 0); | 629 | atomic_set(&cq->usecnt, 0); |
630 | 630 | ||
631 | down(&ib_uverbs_idr_mutex); | 631 | mutex_lock(&ib_uverbs_idr_mutex); |
632 | 632 | ||
633 | retry: | 633 | retry: |
634 | if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) { | 634 | if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) { |
@@ -653,11 +653,11 @@ retry: | |||
653 | goto err_idr; | 653 | goto err_idr; |
654 | } | 654 | } |
655 | 655 | ||
656 | down(&file->mutex); | 656 | mutex_lock(&file->mutex); |
657 | list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); | 657 | list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); |
658 | up(&file->mutex); | 658 | mutex_unlock(&file->mutex); |
659 | 659 | ||
660 | up(&ib_uverbs_idr_mutex); | 660 | mutex_unlock(&ib_uverbs_idr_mutex); |
661 | 661 | ||
662 | return in_len; | 662 | return in_len; |
663 | 663 | ||
@@ -665,7 +665,7 @@ err_idr: | |||
665 | idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); | 665 | idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); |
666 | 666 | ||
667 | err_up: | 667 | err_up: |
668 | up(&ib_uverbs_idr_mutex); | 668 | mutex_unlock(&ib_uverbs_idr_mutex); |
669 | ib_destroy_cq(cq); | 669 | ib_destroy_cq(cq); |
670 | 670 | ||
671 | err: | 671 | err: |
@@ -701,7 +701,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, | |||
701 | goto out_wc; | 701 | goto out_wc; |
702 | } | 702 | } |
703 | 703 | ||
704 | down(&ib_uverbs_idr_mutex); | 704 | mutex_lock(&ib_uverbs_idr_mutex); |
705 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); | 705 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); |
706 | if (!cq || cq->uobject->context != file->ucontext) { | 706 | if (!cq || cq->uobject->context != file->ucontext) { |
707 | ret = -EINVAL; | 707 | ret = -EINVAL; |
@@ -731,7 +731,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, | |||
731 | ret = -EFAULT; | 731 | ret = -EFAULT; |
732 | 732 | ||
733 | out: | 733 | out: |
734 | up(&ib_uverbs_idr_mutex); | 734 | mutex_unlock(&ib_uverbs_idr_mutex); |
735 | kfree(resp); | 735 | kfree(resp); |
736 | 736 | ||
737 | out_wc: | 737 | out_wc: |
@@ -750,14 +750,14 @@ ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file, | |||
750 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 750 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
751 | return -EFAULT; | 751 | return -EFAULT; |
752 | 752 | ||
753 | down(&ib_uverbs_idr_mutex); | 753 | mutex_lock(&ib_uverbs_idr_mutex); |
754 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); | 754 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); |
755 | if (cq && cq->uobject->context == file->ucontext) { | 755 | if (cq && cq->uobject->context == file->ucontext) { |
756 | ib_req_notify_cq(cq, cmd.solicited_only ? | 756 | ib_req_notify_cq(cq, cmd.solicited_only ? |
757 | IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); | 757 | IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); |
758 | ret = in_len; | 758 | ret = in_len; |
759 | } | 759 | } |
760 | up(&ib_uverbs_idr_mutex); | 760 | mutex_unlock(&ib_uverbs_idr_mutex); |
761 | 761 | ||
762 | return ret; | 762 | return ret; |
763 | } | 763 | } |
@@ -779,7 +779,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, | |||
779 | 779 | ||
780 | memset(&resp, 0, sizeof resp); | 780 | memset(&resp, 0, sizeof resp); |
781 | 781 | ||
782 | down(&ib_uverbs_idr_mutex); | 782 | mutex_lock(&ib_uverbs_idr_mutex); |
783 | 783 | ||
784 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); | 784 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); |
785 | if (!cq || cq->uobject->context != file->ucontext) | 785 | if (!cq || cq->uobject->context != file->ucontext) |
@@ -795,9 +795,9 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, | |||
795 | 795 | ||
796 | idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); | 796 | idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); |
797 | 797 | ||
798 | down(&file->mutex); | 798 | mutex_lock(&file->mutex); |
799 | list_del(&uobj->uobject.list); | 799 | list_del(&uobj->uobject.list); |
800 | up(&file->mutex); | 800 | mutex_unlock(&file->mutex); |
801 | 801 | ||
802 | ib_uverbs_release_ucq(file, ev_file, uobj); | 802 | ib_uverbs_release_ucq(file, ev_file, uobj); |
803 | 803 | ||
@@ -811,7 +811,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, | |||
811 | ret = -EFAULT; | 811 | ret = -EFAULT; |
812 | 812 | ||
813 | out: | 813 | out: |
814 | up(&ib_uverbs_idr_mutex); | 814 | mutex_unlock(&ib_uverbs_idr_mutex); |
815 | 815 | ||
816 | return ret ? ret : in_len; | 816 | return ret ? ret : in_len; |
817 | } | 817 | } |
@@ -845,7 +845,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, | |||
845 | if (!uobj) | 845 | if (!uobj) |
846 | return -ENOMEM; | 846 | return -ENOMEM; |
847 | 847 | ||
848 | down(&ib_uverbs_idr_mutex); | 848 | mutex_lock(&ib_uverbs_idr_mutex); |
849 | 849 | ||
850 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); | 850 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); |
851 | scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle); | 851 | scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle); |
@@ -930,11 +930,11 @@ retry: | |||
930 | goto err_idr; | 930 | goto err_idr; |
931 | } | 931 | } |
932 | 932 | ||
933 | down(&file->mutex); | 933 | mutex_lock(&file->mutex); |
934 | list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list); | 934 | list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list); |
935 | up(&file->mutex); | 935 | mutex_unlock(&file->mutex); |
936 | 936 | ||
937 | up(&ib_uverbs_idr_mutex); | 937 | mutex_unlock(&ib_uverbs_idr_mutex); |
938 | 938 | ||
939 | return in_len; | 939 | return in_len; |
940 | 940 | ||
@@ -950,7 +950,7 @@ err_destroy: | |||
950 | atomic_dec(&attr.srq->usecnt); | 950 | atomic_dec(&attr.srq->usecnt); |
951 | 951 | ||
952 | err_up: | 952 | err_up: |
953 | up(&ib_uverbs_idr_mutex); | 953 | mutex_unlock(&ib_uverbs_idr_mutex); |
954 | 954 | ||
955 | kfree(uobj); | 955 | kfree(uobj); |
956 | return ret; | 956 | return ret; |
@@ -972,7 +972,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, | |||
972 | if (!attr) | 972 | if (!attr) |
973 | return -ENOMEM; | 973 | return -ENOMEM; |
974 | 974 | ||
975 | down(&ib_uverbs_idr_mutex); | 975 | mutex_lock(&ib_uverbs_idr_mutex); |
976 | 976 | ||
977 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 977 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
978 | if (!qp || qp->uobject->context != file->ucontext) { | 978 | if (!qp || qp->uobject->context != file->ucontext) { |
@@ -1033,7 +1033,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, | |||
1033 | ret = in_len; | 1033 | ret = in_len; |
1034 | 1034 | ||
1035 | out: | 1035 | out: |
1036 | up(&ib_uverbs_idr_mutex); | 1036 | mutex_unlock(&ib_uverbs_idr_mutex); |
1037 | kfree(attr); | 1037 | kfree(attr); |
1038 | 1038 | ||
1039 | return ret; | 1039 | return ret; |
@@ -1054,7 +1054,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, | |||
1054 | 1054 | ||
1055 | memset(&resp, 0, sizeof resp); | 1055 | memset(&resp, 0, sizeof resp); |
1056 | 1056 | ||
1057 | down(&ib_uverbs_idr_mutex); | 1057 | mutex_lock(&ib_uverbs_idr_mutex); |
1058 | 1058 | ||
1059 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 1059 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
1060 | if (!qp || qp->uobject->context != file->ucontext) | 1060 | if (!qp || qp->uobject->context != file->ucontext) |
@@ -1073,9 +1073,9 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, | |||
1073 | 1073 | ||
1074 | idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); | 1074 | idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); |
1075 | 1075 | ||
1076 | down(&file->mutex); | 1076 | mutex_lock(&file->mutex); |
1077 | list_del(&uobj->uevent.uobject.list); | 1077 | list_del(&uobj->uevent.uobject.list); |
1078 | up(&file->mutex); | 1078 | mutex_unlock(&file->mutex); |
1079 | 1079 | ||
1080 | ib_uverbs_release_uevent(file, &uobj->uevent); | 1080 | ib_uverbs_release_uevent(file, &uobj->uevent); |
1081 | 1081 | ||
@@ -1088,7 +1088,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, | |||
1088 | ret = -EFAULT; | 1088 | ret = -EFAULT; |
1089 | 1089 | ||
1090 | out: | 1090 | out: |
1091 | up(&ib_uverbs_idr_mutex); | 1091 | mutex_unlock(&ib_uverbs_idr_mutex); |
1092 | 1092 | ||
1093 | return ret ? ret : in_len; | 1093 | return ret ? ret : in_len; |
1094 | } | 1094 | } |
@@ -1119,7 +1119,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, | |||
1119 | if (!user_wr) | 1119 | if (!user_wr) |
1120 | return -ENOMEM; | 1120 | return -ENOMEM; |
1121 | 1121 | ||
1122 | down(&ib_uverbs_idr_mutex); | 1122 | mutex_lock(&ib_uverbs_idr_mutex); |
1123 | 1123 | ||
1124 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 1124 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
1125 | if (!qp || qp->uobject->context != file->ucontext) | 1125 | if (!qp || qp->uobject->context != file->ucontext) |
@@ -1224,7 +1224,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, | |||
1224 | ret = -EFAULT; | 1224 | ret = -EFAULT; |
1225 | 1225 | ||
1226 | out: | 1226 | out: |
1227 | up(&ib_uverbs_idr_mutex); | 1227 | mutex_unlock(&ib_uverbs_idr_mutex); |
1228 | 1228 | ||
1229 | while (wr) { | 1229 | while (wr) { |
1230 | next = wr->next; | 1230 | next = wr->next; |
@@ -1341,7 +1341,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file, | |||
1341 | if (IS_ERR(wr)) | 1341 | if (IS_ERR(wr)) |
1342 | return PTR_ERR(wr); | 1342 | return PTR_ERR(wr); |
1343 | 1343 | ||
1344 | down(&ib_uverbs_idr_mutex); | 1344 | mutex_lock(&ib_uverbs_idr_mutex); |
1345 | 1345 | ||
1346 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 1346 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
1347 | if (!qp || qp->uobject->context != file->ucontext) | 1347 | if (!qp || qp->uobject->context != file->ucontext) |
@@ -1362,7 +1362,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file, | |||
1362 | ret = -EFAULT; | 1362 | ret = -EFAULT; |
1363 | 1363 | ||
1364 | out: | 1364 | out: |
1365 | up(&ib_uverbs_idr_mutex); | 1365 | mutex_unlock(&ib_uverbs_idr_mutex); |
1366 | 1366 | ||
1367 | while (wr) { | 1367 | while (wr) { |
1368 | next = wr->next; | 1368 | next = wr->next; |
@@ -1392,7 +1392,7 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file, | |||
1392 | if (IS_ERR(wr)) | 1392 | if (IS_ERR(wr)) |
1393 | return PTR_ERR(wr); | 1393 | return PTR_ERR(wr); |
1394 | 1394 | ||
1395 | down(&ib_uverbs_idr_mutex); | 1395 | mutex_lock(&ib_uverbs_idr_mutex); |
1396 | 1396 | ||
1397 | srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); | 1397 | srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); |
1398 | if (!srq || srq->uobject->context != file->ucontext) | 1398 | if (!srq || srq->uobject->context != file->ucontext) |
@@ -1413,7 +1413,7 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file, | |||
1413 | ret = -EFAULT; | 1413 | ret = -EFAULT; |
1414 | 1414 | ||
1415 | out: | 1415 | out: |
1416 | up(&ib_uverbs_idr_mutex); | 1416 | mutex_unlock(&ib_uverbs_idr_mutex); |
1417 | 1417 | ||
1418 | while (wr) { | 1418 | while (wr) { |
1419 | next = wr->next; | 1419 | next = wr->next; |
@@ -1446,7 +1446,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, | |||
1446 | if (!uobj) | 1446 | if (!uobj) |
1447 | return -ENOMEM; | 1447 | return -ENOMEM; |
1448 | 1448 | ||
1449 | down(&ib_uverbs_idr_mutex); | 1449 | mutex_lock(&ib_uverbs_idr_mutex); |
1450 | 1450 | ||
1451 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); | 1451 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); |
1452 | if (!pd || pd->uobject->context != file->ucontext) { | 1452 | if (!pd || pd->uobject->context != file->ucontext) { |
@@ -1498,11 +1498,11 @@ retry: | |||
1498 | goto err_idr; | 1498 | goto err_idr; |
1499 | } | 1499 | } |
1500 | 1500 | ||
1501 | down(&file->mutex); | 1501 | mutex_lock(&file->mutex); |
1502 | list_add_tail(&uobj->list, &file->ucontext->ah_list); | 1502 | list_add_tail(&uobj->list, &file->ucontext->ah_list); |
1503 | up(&file->mutex); | 1503 | mutex_unlock(&file->mutex); |
1504 | 1504 | ||
1505 | up(&ib_uverbs_idr_mutex); | 1505 | mutex_unlock(&ib_uverbs_idr_mutex); |
1506 | 1506 | ||
1507 | return in_len; | 1507 | return in_len; |
1508 | 1508 | ||
@@ -1513,7 +1513,7 @@ err_destroy: | |||
1513 | ib_destroy_ah(ah); | 1513 | ib_destroy_ah(ah); |
1514 | 1514 | ||
1515 | err_up: | 1515 | err_up: |
1516 | up(&ib_uverbs_idr_mutex); | 1516 | mutex_unlock(&ib_uverbs_idr_mutex); |
1517 | 1517 | ||
1518 | kfree(uobj); | 1518 | kfree(uobj); |
1519 | return ret; | 1519 | return ret; |
@@ -1530,7 +1530,7 @@ ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file, | |||
1530 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 1530 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
1531 | return -EFAULT; | 1531 | return -EFAULT; |
1532 | 1532 | ||
1533 | down(&ib_uverbs_idr_mutex); | 1533 | mutex_lock(&ib_uverbs_idr_mutex); |
1534 | 1534 | ||
1535 | ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle); | 1535 | ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle); |
1536 | if (!ah || ah->uobject->context != file->ucontext) | 1536 | if (!ah || ah->uobject->context != file->ucontext) |
@@ -1544,14 +1544,14 @@ ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file, | |||
1544 | 1544 | ||
1545 | idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle); | 1545 | idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle); |
1546 | 1546 | ||
1547 | down(&file->mutex); | 1547 | mutex_lock(&file->mutex); |
1548 | list_del(&uobj->list); | 1548 | list_del(&uobj->list); |
1549 | up(&file->mutex); | 1549 | mutex_unlock(&file->mutex); |
1550 | 1550 | ||
1551 | kfree(uobj); | 1551 | kfree(uobj); |
1552 | 1552 | ||
1553 | out: | 1553 | out: |
1554 | up(&ib_uverbs_idr_mutex); | 1554 | mutex_unlock(&ib_uverbs_idr_mutex); |
1555 | 1555 | ||
1556 | return ret ? ret : in_len; | 1556 | return ret ? ret : in_len; |
1557 | } | 1557 | } |
@@ -1569,7 +1569,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, | |||
1569 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 1569 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
1570 | return -EFAULT; | 1570 | return -EFAULT; |
1571 | 1571 | ||
1572 | down(&ib_uverbs_idr_mutex); | 1572 | mutex_lock(&ib_uverbs_idr_mutex); |
1573 | 1573 | ||
1574 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 1574 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
1575 | if (!qp || qp->uobject->context != file->ucontext) | 1575 | if (!qp || qp->uobject->context != file->ucontext) |
@@ -1602,7 +1602,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, | |||
1602 | kfree(mcast); | 1602 | kfree(mcast); |
1603 | 1603 | ||
1604 | out: | 1604 | out: |
1605 | up(&ib_uverbs_idr_mutex); | 1605 | mutex_unlock(&ib_uverbs_idr_mutex); |
1606 | 1606 | ||
1607 | return ret ? ret : in_len; | 1607 | return ret ? ret : in_len; |
1608 | } | 1608 | } |
@@ -1620,7 +1620,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, | |||
1620 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 1620 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
1621 | return -EFAULT; | 1621 | return -EFAULT; |
1622 | 1622 | ||
1623 | down(&ib_uverbs_idr_mutex); | 1623 | mutex_lock(&ib_uverbs_idr_mutex); |
1624 | 1624 | ||
1625 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 1625 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
1626 | if (!qp || qp->uobject->context != file->ucontext) | 1626 | if (!qp || qp->uobject->context != file->ucontext) |
@@ -1641,7 +1641,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, | |||
1641 | } | 1641 | } |
1642 | 1642 | ||
1643 | out: | 1643 | out: |
1644 | up(&ib_uverbs_idr_mutex); | 1644 | mutex_unlock(&ib_uverbs_idr_mutex); |
1645 | 1645 | ||
1646 | return ret ? ret : in_len; | 1646 | return ret ? ret : in_len; |
1647 | } | 1647 | } |
@@ -1673,7 +1673,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, | |||
1673 | if (!uobj) | 1673 | if (!uobj) |
1674 | return -ENOMEM; | 1674 | return -ENOMEM; |
1675 | 1675 | ||
1676 | down(&ib_uverbs_idr_mutex); | 1676 | mutex_lock(&ib_uverbs_idr_mutex); |
1677 | 1677 | ||
1678 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); | 1678 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); |
1679 | 1679 | ||
@@ -1730,11 +1730,11 @@ retry: | |||
1730 | goto err_idr; | 1730 | goto err_idr; |
1731 | } | 1731 | } |
1732 | 1732 | ||
1733 | down(&file->mutex); | 1733 | mutex_lock(&file->mutex); |
1734 | list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); | 1734 | list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); |
1735 | up(&file->mutex); | 1735 | mutex_unlock(&file->mutex); |
1736 | 1736 | ||
1737 | up(&ib_uverbs_idr_mutex); | 1737 | mutex_unlock(&ib_uverbs_idr_mutex); |
1738 | 1738 | ||
1739 | return in_len; | 1739 | return in_len; |
1740 | 1740 | ||
@@ -1746,7 +1746,7 @@ err_destroy: | |||
1746 | atomic_dec(&pd->usecnt); | 1746 | atomic_dec(&pd->usecnt); |
1747 | 1747 | ||
1748 | err_up: | 1748 | err_up: |
1749 | up(&ib_uverbs_idr_mutex); | 1749 | mutex_unlock(&ib_uverbs_idr_mutex); |
1750 | 1750 | ||
1751 | kfree(uobj); | 1751 | kfree(uobj); |
1752 | return ret; | 1752 | return ret; |
@@ -1764,7 +1764,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, | |||
1764 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 1764 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
1765 | return -EFAULT; | 1765 | return -EFAULT; |
1766 | 1766 | ||
1767 | down(&ib_uverbs_idr_mutex); | 1767 | mutex_lock(&ib_uverbs_idr_mutex); |
1768 | 1768 | ||
1769 | srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); | 1769 | srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); |
1770 | if (!srq || srq->uobject->context != file->ucontext) { | 1770 | if (!srq || srq->uobject->context != file->ucontext) { |
@@ -1778,7 +1778,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, | |||
1778 | ret = ib_modify_srq(srq, &attr, cmd.attr_mask); | 1778 | ret = ib_modify_srq(srq, &attr, cmd.attr_mask); |
1779 | 1779 | ||
1780 | out: | 1780 | out: |
1781 | up(&ib_uverbs_idr_mutex); | 1781 | mutex_unlock(&ib_uverbs_idr_mutex); |
1782 | 1782 | ||
1783 | return ret ? ret : in_len; | 1783 | return ret ? ret : in_len; |
1784 | } | 1784 | } |
@@ -1796,7 +1796,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, | |||
1796 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 1796 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
1797 | return -EFAULT; | 1797 | return -EFAULT; |
1798 | 1798 | ||
1799 | down(&ib_uverbs_idr_mutex); | 1799 | mutex_lock(&ib_uverbs_idr_mutex); |
1800 | 1800 | ||
1801 | memset(&resp, 0, sizeof resp); | 1801 | memset(&resp, 0, sizeof resp); |
1802 | 1802 | ||
@@ -1812,9 +1812,9 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, | |||
1812 | 1812 | ||
1813 | idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); | 1813 | idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); |
1814 | 1814 | ||
1815 | down(&file->mutex); | 1815 | mutex_lock(&file->mutex); |
1816 | list_del(&uobj->uobject.list); | 1816 | list_del(&uobj->uobject.list); |
1817 | up(&file->mutex); | 1817 | mutex_unlock(&file->mutex); |
1818 | 1818 | ||
1819 | ib_uverbs_release_uevent(file, uobj); | 1819 | ib_uverbs_release_uevent(file, uobj); |
1820 | 1820 | ||
@@ -1827,7 +1827,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, | |||
1827 | ret = -EFAULT; | 1827 | ret = -EFAULT; |
1828 | 1828 | ||
1829 | out: | 1829 | out: |
1830 | up(&ib_uverbs_idr_mutex); | 1830 | mutex_unlock(&ib_uverbs_idr_mutex); |
1831 | 1831 | ||
1832 | return ret ? ret : in_len; | 1832 | return ret ? ret : in_len; |
1833 | } | 1833 | } |
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 81737bd6faea..96ea79b63df7 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
@@ -66,7 +66,7 @@ enum { | |||
66 | 66 | ||
67 | static struct class *uverbs_class; | 67 | static struct class *uverbs_class; |
68 | 68 | ||
69 | DECLARE_MUTEX(ib_uverbs_idr_mutex); | 69 | DEFINE_MUTEX(ib_uverbs_idr_mutex); |
70 | DEFINE_IDR(ib_uverbs_pd_idr); | 70 | DEFINE_IDR(ib_uverbs_pd_idr); |
71 | DEFINE_IDR(ib_uverbs_mr_idr); | 71 | DEFINE_IDR(ib_uverbs_mr_idr); |
72 | DEFINE_IDR(ib_uverbs_mw_idr); | 72 | DEFINE_IDR(ib_uverbs_mw_idr); |
@@ -180,7 +180,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, | |||
180 | if (!context) | 180 | if (!context) |
181 | return 0; | 181 | return 0; |
182 | 182 | ||
183 | down(&ib_uverbs_idr_mutex); | 183 | mutex_lock(&ib_uverbs_idr_mutex); |
184 | 184 | ||
185 | list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) { | 185 | list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) { |
186 | struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id); | 186 | struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id); |
@@ -250,7 +250,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, | |||
250 | kfree(uobj); | 250 | kfree(uobj); |
251 | } | 251 | } |
252 | 252 | ||
253 | up(&ib_uverbs_idr_mutex); | 253 | mutex_unlock(&ib_uverbs_idr_mutex); |
254 | 254 | ||
255 | return context->device->dealloc_ucontext(context); | 255 | return context->device->dealloc_ucontext(context); |
256 | } | 256 | } |
@@ -653,7 +653,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) | |||
653 | file->ucontext = NULL; | 653 | file->ucontext = NULL; |
654 | file->async_file = NULL; | 654 | file->async_file = NULL; |
655 | kref_init(&file->ref); | 655 | kref_init(&file->ref); |
656 | init_MUTEX(&file->mutex); | 656 | mutex_init(&file->mutex); |
657 | 657 | ||
658 | filp->private_data = file; | 658 | filp->private_data = file; |
659 | 659 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index 22fdc446f25c..a14eed08a0fc 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c | |||
@@ -163,6 +163,11 @@ int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah) | |||
163 | return 0; | 163 | return 0; |
164 | } | 164 | } |
165 | 165 | ||
166 | int mthca_ah_grh_present(struct mthca_ah *ah) | ||
167 | { | ||
168 | return !!(ah->av->g_slid & 0x80); | ||
169 | } | ||
170 | |||
166 | int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, | 171 | int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, |
167 | struct ib_ud_header *header) | 172 | struct ib_ud_header *header) |
168 | { | 173 | { |
@@ -172,8 +177,7 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, | |||
172 | header->lrh.service_level = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; | 177 | header->lrh.service_level = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; |
173 | header->lrh.destination_lid = ah->av->dlid; | 178 | header->lrh.destination_lid = ah->av->dlid; |
174 | header->lrh.source_lid = cpu_to_be16(ah->av->g_slid & 0x7f); | 179 | header->lrh.source_lid = cpu_to_be16(ah->av->g_slid & 0x7f); |
175 | if (ah->av->g_slid & 0x80) { | 180 | if (mthca_ah_grh_present(ah)) { |
176 | header->grh_present = 1; | ||
177 | header->grh.traffic_class = | 181 | header->grh.traffic_class = |
178 | (be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff; | 182 | (be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff; |
179 | header->grh.flow_label = | 183 | header->grh.flow_label = |
@@ -184,8 +188,6 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, | |||
184 | &header->grh.source_gid); | 188 | &header->grh.source_gid); |
185 | memcpy(header->grh.destination_gid.raw, | 189 | memcpy(header->grh.destination_gid.raw, |
186 | ah->av->dgid, 16); | 190 | ah->av->dgid, 16); |
187 | } else { | ||
188 | header->grh_present = 0; | ||
189 | } | 191 | } |
190 | 192 | ||
191 | return 0; | 193 | return 0; |
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 22ac72bc20c3..be1791be627b 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c | |||
@@ -606,7 +606,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, | |||
606 | err = -EINVAL; | 606 | err = -EINVAL; |
607 | goto out; | 607 | goto out; |
608 | } | 608 | } |
609 | for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i) { | 609 | for (i = 0; i < mthca_icm_size(&iter) >> lg; ++i) { |
610 | if (virt != -1) { | 610 | if (virt != -1) { |
611 | pages[nent * 2] = cpu_to_be64(virt); | 611 | pages[nent * 2] = cpu_to_be64(virt); |
612 | virt += 1 << lg; | 612 | virt += 1 << lg; |
@@ -727,8 +727,8 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) | |||
727 | * system pages needed. | 727 | * system pages needed. |
728 | */ | 728 | */ |
729 | dev->fw.arbel.fw_pages = | 729 | dev->fw.arbel.fw_pages = |
730 | (dev->fw.arbel.fw_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> | 730 | ALIGN(dev->fw.arbel.fw_pages, PAGE_SIZE >> 12) >> |
731 | (PAGE_SHIFT - 12); | 731 | (PAGE_SHIFT - 12); |
732 | 732 | ||
733 | mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n", | 733 | mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n", |
734 | (unsigned long long) dev->fw.arbel.clr_int_base, | 734 | (unsigned long long) dev->fw.arbel.clr_int_base, |
@@ -1445,6 +1445,7 @@ int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages, | |||
1445 | * pages needed. | 1445 | * pages needed. |
1446 | */ | 1446 | */ |
1447 | *aux_pages = (*aux_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> (PAGE_SHIFT - 12); | 1447 | *aux_pages = (*aux_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> (PAGE_SHIFT - 12); |
1448 | *aux_pages = ALIGN(*aux_pages, PAGE_SIZE >> 12) >> (PAGE_SHIFT - 12); | ||
1448 | 1449 | ||
1449 | return 0; | 1450 | return 0; |
1450 | } | 1451 | } |
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index 795b379260bf..a104ab041ea3 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h | |||
@@ -520,6 +520,7 @@ int mthca_create_ah(struct mthca_dev *dev, | |||
520 | int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah); | 520 | int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah); |
521 | int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, | 521 | int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, |
522 | struct ib_ud_header *header); | 522 | struct ib_ud_header *header); |
523 | int mthca_ah_grh_present(struct mthca_ah *ah); | ||
523 | 524 | ||
524 | int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); | 525 | int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); |
525 | int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); | 526 | int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); |
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index e8a948f087c0..2eabb27804cd 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c | |||
@@ -45,6 +45,7 @@ | |||
45 | enum { | 45 | enum { |
46 | MTHCA_NUM_ASYNC_EQE = 0x80, | 46 | MTHCA_NUM_ASYNC_EQE = 0x80, |
47 | MTHCA_NUM_CMD_EQE = 0x80, | 47 | MTHCA_NUM_CMD_EQE = 0x80, |
48 | MTHCA_NUM_SPARE_EQE = 0x80, | ||
48 | MTHCA_EQ_ENTRY_SIZE = 0x20 | 49 | MTHCA_EQ_ENTRY_SIZE = 0x20 |
49 | }; | 50 | }; |
50 | 51 | ||
@@ -277,11 +278,10 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq) | |||
277 | { | 278 | { |
278 | struct mthca_eqe *eqe; | 279 | struct mthca_eqe *eqe; |
279 | int disarm_cqn; | 280 | int disarm_cqn; |
280 | int eqes_found = 0; | 281 | int eqes_found = 0; |
282 | int set_ci = 0; | ||
281 | 283 | ||
282 | while ((eqe = next_eqe_sw(eq))) { | 284 | while ((eqe = next_eqe_sw(eq))) { |
283 | int set_ci = 0; | ||
284 | |||
285 | /* | 285 | /* |
286 | * Make sure we read EQ entry contents after we've | 286 | * Make sure we read EQ entry contents after we've |
287 | * checked the ownership bit. | 287 | * checked the ownership bit. |
@@ -345,12 +345,6 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq) | |||
345 | be16_to_cpu(eqe->event.cmd.token), | 345 | be16_to_cpu(eqe->event.cmd.token), |
346 | eqe->event.cmd.status, | 346 | eqe->event.cmd.status, |
347 | be64_to_cpu(eqe->event.cmd.out_param)); | 347 | be64_to_cpu(eqe->event.cmd.out_param)); |
348 | /* | ||
349 | * cmd_event() may add more commands. | ||
350 | * The card will think the queue has overflowed if | ||
351 | * we don't tell it we've been processing events. | ||
352 | */ | ||
353 | set_ci = 1; | ||
354 | break; | 348 | break; |
355 | 349 | ||
356 | case MTHCA_EVENT_TYPE_PORT_CHANGE: | 350 | case MTHCA_EVENT_TYPE_PORT_CHANGE: |
@@ -385,8 +379,16 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq) | |||
385 | set_eqe_hw(eqe); | 379 | set_eqe_hw(eqe); |
386 | ++eq->cons_index; | 380 | ++eq->cons_index; |
387 | eqes_found = 1; | 381 | eqes_found = 1; |
382 | ++set_ci; | ||
388 | 383 | ||
389 | if (unlikely(set_ci)) { | 384 | /* |
385 | * The HCA will think the queue has overflowed if we | ||
386 | * don't tell it we've been processing events. We | ||
387 | * create our EQs with MTHCA_NUM_SPARE_EQE extra | ||
388 | * entries, so we must update our consumer index at | ||
389 | * least that often. | ||
390 | */ | ||
391 | if (unlikely(set_ci >= MTHCA_NUM_SPARE_EQE)) { | ||
390 | /* | 392 | /* |
391 | * Conditional on hca_type is OK here because | 393 | * Conditional on hca_type is OK here because |
392 | * this is a rare case, not the fast path. | 394 | * this is a rare case, not the fast path. |
@@ -862,19 +864,19 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev) | |||
862 | intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ? | 864 | intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ? |
863 | 128 : dev->eq_table.inta_pin; | 865 | 128 : dev->eq_table.inta_pin; |
864 | 866 | ||
865 | err = mthca_create_eq(dev, dev->limits.num_cqs, | 867 | err = mthca_create_eq(dev, dev->limits.num_cqs + MTHCA_NUM_SPARE_EQE, |
866 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr, | 868 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr, |
867 | &dev->eq_table.eq[MTHCA_EQ_COMP]); | 869 | &dev->eq_table.eq[MTHCA_EQ_COMP]); |
868 | if (err) | 870 | if (err) |
869 | goto err_out_unmap; | 871 | goto err_out_unmap; |
870 | 872 | ||
871 | err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE, | 873 | err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE + MTHCA_NUM_SPARE_EQE, |
872 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr, | 874 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr, |
873 | &dev->eq_table.eq[MTHCA_EQ_ASYNC]); | 875 | &dev->eq_table.eq[MTHCA_EQ_ASYNC]); |
874 | if (err) | 876 | if (err) |
875 | goto err_out_comp; | 877 | goto err_out_comp; |
876 | 878 | ||
877 | err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE, | 879 | err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE + MTHCA_NUM_SPARE_EQE, |
878 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 130 : intr, | 880 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 130 : intr, |
879 | &dev->eq_table.eq[MTHCA_EQ_CMD]); | 881 | &dev->eq_table.eq[MTHCA_EQ_CMD]); |
880 | if (err) | 882 | if (err) |
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 4cc7e2846df1..484a7e6b7f8c 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c | |||
@@ -33,7 +33,7 @@ | |||
33 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 33 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
34 | * SOFTWARE. | 34 | * SOFTWARE. |
35 | * | 35 | * |
36 | * $Id: mthca_provider.c 1397 2004-12-28 05:09:00Z roland $ | 36 | * $Id: mthca_provider.c 4859 2006-01-09 21:55:10Z roland $ |
37 | */ | 37 | */ |
38 | 38 | ||
39 | #include <rdma/ib_smi.h> | 39 | #include <rdma/ib_smi.h> |
@@ -45,6 +45,14 @@ | |||
45 | #include "mthca_user.h" | 45 | #include "mthca_user.h" |
46 | #include "mthca_memfree.h" | 46 | #include "mthca_memfree.h" |
47 | 47 | ||
48 | static void init_query_mad(struct ib_smp *mad) | ||
49 | { | ||
50 | mad->base_version = 1; | ||
51 | mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | ||
52 | mad->class_version = 1; | ||
53 | mad->method = IB_MGMT_METHOD_GET; | ||
54 | } | ||
55 | |||
48 | static int mthca_query_device(struct ib_device *ibdev, | 56 | static int mthca_query_device(struct ib_device *ibdev, |
49 | struct ib_device_attr *props) | 57 | struct ib_device_attr *props) |
50 | { | 58 | { |
@@ -55,7 +63,7 @@ static int mthca_query_device(struct ib_device *ibdev, | |||
55 | 63 | ||
56 | u8 status; | 64 | u8 status; |
57 | 65 | ||
58 | in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); | 66 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
59 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | 67 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); |
60 | if (!in_mad || !out_mad) | 68 | if (!in_mad || !out_mad) |
61 | goto out; | 69 | goto out; |
@@ -64,12 +72,8 @@ static int mthca_query_device(struct ib_device *ibdev, | |||
64 | 72 | ||
65 | props->fw_ver = mdev->fw_ver; | 73 | props->fw_ver = mdev->fw_ver; |
66 | 74 | ||
67 | memset(in_mad, 0, sizeof *in_mad); | 75 | init_query_mad(in_mad); |
68 | in_mad->base_version = 1; | 76 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; |
69 | in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | ||
70 | in_mad->class_version = 1; | ||
71 | in_mad->method = IB_MGMT_METHOD_GET; | ||
72 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; | ||
73 | 77 | ||
74 | err = mthca_MAD_IFC(mdev, 1, 1, | 78 | err = mthca_MAD_IFC(mdev, 1, 1, |
75 | 1, NULL, NULL, in_mad, out_mad, | 79 | 1, NULL, NULL, in_mad, out_mad, |
@@ -87,7 +91,6 @@ static int mthca_query_device(struct ib_device *ibdev, | |||
87 | props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); | 91 | props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); |
88 | props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32)); | 92 | props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32)); |
89 | memcpy(&props->sys_image_guid, out_mad->data + 4, 8); | 93 | memcpy(&props->sys_image_guid, out_mad->data + 4, 8); |
90 | memcpy(&props->node_guid, out_mad->data + 12, 8); | ||
91 | 94 | ||
92 | props->max_mr_size = ~0ull; | 95 | props->max_mr_size = ~0ull; |
93 | props->page_size_cap = mdev->limits.page_size_cap; | 96 | props->page_size_cap = mdev->limits.page_size_cap; |
@@ -128,20 +131,16 @@ static int mthca_query_port(struct ib_device *ibdev, | |||
128 | int err = -ENOMEM; | 131 | int err = -ENOMEM; |
129 | u8 status; | 132 | u8 status; |
130 | 133 | ||
131 | in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); | 134 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
132 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | 135 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); |
133 | if (!in_mad || !out_mad) | 136 | if (!in_mad || !out_mad) |
134 | goto out; | 137 | goto out; |
135 | 138 | ||
136 | memset(props, 0, sizeof *props); | 139 | memset(props, 0, sizeof *props); |
137 | 140 | ||
138 | memset(in_mad, 0, sizeof *in_mad); | 141 | init_query_mad(in_mad); |
139 | in_mad->base_version = 1; | 142 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; |
140 | in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | 143 | in_mad->attr_mod = cpu_to_be32(port); |
141 | in_mad->class_version = 1; | ||
142 | in_mad->method = IB_MGMT_METHOD_GET; | ||
143 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; | ||
144 | in_mad->attr_mod = cpu_to_be32(port); | ||
145 | 144 | ||
146 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, | 145 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, |
147 | port, NULL, NULL, in_mad, out_mad, | 146 | port, NULL, NULL, in_mad, out_mad, |
@@ -220,18 +219,14 @@ static int mthca_query_pkey(struct ib_device *ibdev, | |||
220 | int err = -ENOMEM; | 219 | int err = -ENOMEM; |
221 | u8 status; | 220 | u8 status; |
222 | 221 | ||
223 | in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); | 222 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
224 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | 223 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); |
225 | if (!in_mad || !out_mad) | 224 | if (!in_mad || !out_mad) |
226 | goto out; | 225 | goto out; |
227 | 226 | ||
228 | memset(in_mad, 0, sizeof *in_mad); | 227 | init_query_mad(in_mad); |
229 | in_mad->base_version = 1; | 228 | in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; |
230 | in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | 229 | in_mad->attr_mod = cpu_to_be32(index / 32); |
231 | in_mad->class_version = 1; | ||
232 | in_mad->method = IB_MGMT_METHOD_GET; | ||
233 | in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; | ||
234 | in_mad->attr_mod = cpu_to_be32(index / 32); | ||
235 | 230 | ||
236 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, | 231 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, |
237 | port, NULL, NULL, in_mad, out_mad, | 232 | port, NULL, NULL, in_mad, out_mad, |
@@ -259,18 +254,14 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port, | |||
259 | int err = -ENOMEM; | 254 | int err = -ENOMEM; |
260 | u8 status; | 255 | u8 status; |
261 | 256 | ||
262 | in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); | 257 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
263 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | 258 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); |
264 | if (!in_mad || !out_mad) | 259 | if (!in_mad || !out_mad) |
265 | goto out; | 260 | goto out; |
266 | 261 | ||
267 | memset(in_mad, 0, sizeof *in_mad); | 262 | init_query_mad(in_mad); |
268 | in_mad->base_version = 1; | 263 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; |
269 | in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | 264 | in_mad->attr_mod = cpu_to_be32(port); |
270 | in_mad->class_version = 1; | ||
271 | in_mad->method = IB_MGMT_METHOD_GET; | ||
272 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; | ||
273 | in_mad->attr_mod = cpu_to_be32(port); | ||
274 | 265 | ||
275 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, | 266 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, |
276 | port, NULL, NULL, in_mad, out_mad, | 267 | port, NULL, NULL, in_mad, out_mad, |
@@ -284,13 +275,9 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port, | |||
284 | 275 | ||
285 | memcpy(gid->raw, out_mad->data + 8, 8); | 276 | memcpy(gid->raw, out_mad->data + 8, 8); |
286 | 277 | ||
287 | memset(in_mad, 0, sizeof *in_mad); | 278 | init_query_mad(in_mad); |
288 | in_mad->base_version = 1; | 279 | in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; |
289 | in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | 280 | in_mad->attr_mod = cpu_to_be32(index / 8); |
290 | in_mad->class_version = 1; | ||
291 | in_mad->method = IB_MGMT_METHOD_GET; | ||
292 | in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; | ||
293 | in_mad->attr_mod = cpu_to_be32(index / 8); | ||
294 | 281 | ||
295 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, | 282 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, |
296 | port, NULL, NULL, in_mad, out_mad, | 283 | port, NULL, NULL, in_mad, out_mad, |
@@ -458,8 +445,10 @@ static struct ib_srq *mthca_create_srq(struct ib_pd *pd, | |||
458 | if (pd->uobject) { | 445 | if (pd->uobject) { |
459 | context = to_mucontext(pd->uobject->context); | 446 | context = to_mucontext(pd->uobject->context); |
460 | 447 | ||
461 | if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) | 448 | if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { |
462 | return ERR_PTR(-EFAULT); | 449 | err = -EFAULT; |
450 | goto err_free; | ||
451 | } | ||
463 | 452 | ||
464 | err = mthca_map_user_db(to_mdev(pd->device), &context->uar, | 453 | err = mthca_map_user_db(to_mdev(pd->device), &context->uar, |
465 | context->db_tab, ucmd.db_index, | 454 | context->db_tab, ucmd.db_index, |
@@ -535,8 +524,10 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd, | |||
535 | if (pd->uobject) { | 524 | if (pd->uobject) { |
536 | context = to_mucontext(pd->uobject->context); | 525 | context = to_mucontext(pd->uobject->context); |
537 | 526 | ||
538 | if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) | 527 | if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { |
528 | kfree(qp); | ||
539 | return ERR_PTR(-EFAULT); | 529 | return ERR_PTR(-EFAULT); |
530 | } | ||
540 | 531 | ||
541 | err = mthca_map_user_db(to_mdev(pd->device), &context->uar, | 532 | err = mthca_map_user_db(to_mdev(pd->device), &context->uar, |
542 | context->db_tab, | 533 | context->db_tab, |
@@ -783,24 +774,20 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd *pd, | |||
783 | if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK)) | 774 | if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK)) |
784 | return ERR_PTR(-EINVAL); | 775 | return ERR_PTR(-EINVAL); |
785 | 776 | ||
786 | if (num_phys_buf > 1 && | ||
787 | ((buffer_list[0].addr + buffer_list[0].size) & ~PAGE_MASK)) | ||
788 | return ERR_PTR(-EINVAL); | ||
789 | |||
790 | mask = 0; | 777 | mask = 0; |
791 | total_size = 0; | 778 | total_size = 0; |
792 | for (i = 0; i < num_phys_buf; ++i) { | 779 | for (i = 0; i < num_phys_buf; ++i) { |
793 | if (i != 0 && buffer_list[i].addr & ~PAGE_MASK) | 780 | if (i != 0) |
794 | return ERR_PTR(-EINVAL); | 781 | mask |= buffer_list[i].addr; |
795 | if (i != 0 && i != num_phys_buf - 1 && | 782 | if (i != num_phys_buf - 1) |
796 | (buffer_list[i].size & ~PAGE_MASK)) | 783 | mask |= buffer_list[i].addr + buffer_list[i].size; |
797 | return ERR_PTR(-EINVAL); | ||
798 | 784 | ||
799 | total_size += buffer_list[i].size; | 785 | total_size += buffer_list[i].size; |
800 | if (i > 0) | ||
801 | mask |= buffer_list[i].addr; | ||
802 | } | 786 | } |
803 | 787 | ||
788 | if (mask & ~PAGE_MASK) | ||
789 | return ERR_PTR(-EINVAL); | ||
790 | |||
804 | /* Find largest page shift we can use to cover buffers */ | 791 | /* Find largest page shift we can use to cover buffers */ |
805 | for (shift = PAGE_SHIFT; shift < 31; ++shift) | 792 | for (shift = PAGE_SHIFT; shift < 31; ++shift) |
806 | if (num_phys_buf > 1) { | 793 | if (num_phys_buf > 1) { |
@@ -1070,11 +1057,48 @@ static struct class_device_attribute *mthca_class_attributes[] = { | |||
1070 | &class_device_attr_board_id | 1057 | &class_device_attr_board_id |
1071 | }; | 1058 | }; |
1072 | 1059 | ||
1060 | static int mthca_init_node_data(struct mthca_dev *dev) | ||
1061 | { | ||
1062 | struct ib_smp *in_mad = NULL; | ||
1063 | struct ib_smp *out_mad = NULL; | ||
1064 | int err = -ENOMEM; | ||
1065 | u8 status; | ||
1066 | |||
1067 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); | ||
1068 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | ||
1069 | if (!in_mad || !out_mad) | ||
1070 | goto out; | ||
1071 | |||
1072 | init_query_mad(in_mad); | ||
1073 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; | ||
1074 | |||
1075 | err = mthca_MAD_IFC(dev, 1, 1, | ||
1076 | 1, NULL, NULL, in_mad, out_mad, | ||
1077 | &status); | ||
1078 | if (err) | ||
1079 | goto out; | ||
1080 | if (status) { | ||
1081 | err = -EINVAL; | ||
1082 | goto out; | ||
1083 | } | ||
1084 | |||
1085 | memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8); | ||
1086 | |||
1087 | out: | ||
1088 | kfree(in_mad); | ||
1089 | kfree(out_mad); | ||
1090 | return err; | ||
1091 | } | ||
1092 | |||
1073 | int mthca_register_device(struct mthca_dev *dev) | 1093 | int mthca_register_device(struct mthca_dev *dev) |
1074 | { | 1094 | { |
1075 | int ret; | 1095 | int ret; |
1076 | int i; | 1096 | int i; |
1077 | 1097 | ||
1098 | ret = mthca_init_node_data(dev); | ||
1099 | if (ret) | ||
1100 | return ret; | ||
1101 | |||
1078 | strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX); | 1102 | strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX); |
1079 | dev->ib_dev.owner = THIS_MODULE; | 1103 | dev->ib_dev.owner = THIS_MODULE; |
1080 | 1104 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 564b6d51c394..fba608ed7df2 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c | |||
@@ -1434,7 +1434,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp, | |||
1434 | u16 pkey; | 1434 | u16 pkey; |
1435 | 1435 | ||
1436 | ib_ud_header_init(256, /* assume a MAD */ | 1436 | ib_ud_header_init(256, /* assume a MAD */ |
1437 | sqp->ud_header.grh_present, | 1437 | mthca_ah_grh_present(to_mah(wr->wr.ud.ah)), |
1438 | &sqp->ud_header); | 1438 | &sqp->ud_header); |
1439 | 1439 | ||
1440 | err = mthca_read_ah(dev, to_mah(wr->wr.ud.ah), &sqp->ud_header); | 1440 | err = mthca_read_ah(dev, to_mah(wr->wr.ud.ah), &sqp->ud_header); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 9923a15a9996..e0a5412b7e68 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
@@ -45,11 +45,11 @@ | |||
45 | #include <linux/config.h> | 45 | #include <linux/config.h> |
46 | #include <linux/kref.h> | 46 | #include <linux/kref.h> |
47 | #include <linux/if_infiniband.h> | 47 | #include <linux/if_infiniband.h> |
48 | #include <linux/mutex.h> | ||
48 | 49 | ||
49 | #include <net/neighbour.h> | 50 | #include <net/neighbour.h> |
50 | 51 | ||
51 | #include <asm/atomic.h> | 52 | #include <asm/atomic.h> |
52 | #include <asm/semaphore.h> | ||
53 | 53 | ||
54 | #include <rdma/ib_verbs.h> | 54 | #include <rdma/ib_verbs.h> |
55 | #include <rdma/ib_pack.h> | 55 | #include <rdma/ib_pack.h> |
@@ -123,8 +123,8 @@ struct ipoib_dev_priv { | |||
123 | 123 | ||
124 | unsigned long flags; | 124 | unsigned long flags; |
125 | 125 | ||
126 | struct semaphore mcast_mutex; | 126 | struct mutex mcast_mutex; |
127 | struct semaphore vlan_mutex; | 127 | struct mutex vlan_mutex; |
128 | 128 | ||
129 | struct rb_root path_tree; | 129 | struct rb_root path_tree; |
130 | struct list_head path_list; | 130 | struct list_head path_list; |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 23885801b6d2..86bcdd72a107 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(data_debug_level, | |||
52 | 52 | ||
53 | #define IPOIB_OP_RECV (1ul << 31) | 53 | #define IPOIB_OP_RECV (1ul << 31) |
54 | 54 | ||
55 | static DECLARE_MUTEX(pkey_sem); | 55 | static DEFINE_MUTEX(pkey_mutex); |
56 | 56 | ||
57 | struct ipoib_ah *ipoib_create_ah(struct net_device *dev, | 57 | struct ipoib_ah *ipoib_create_ah(struct net_device *dev, |
58 | struct ib_pd *pd, struct ib_ah_attr *attr) | 58 | struct ib_pd *pd, struct ib_ah_attr *attr) |
@@ -445,25 +445,16 @@ int ipoib_ib_dev_down(struct net_device *dev) | |||
445 | 445 | ||
446 | /* Shutdown the P_Key thread if still active */ | 446 | /* Shutdown the P_Key thread if still active */ |
447 | if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { | 447 | if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { |
448 | down(&pkey_sem); | 448 | mutex_lock(&pkey_mutex); |
449 | set_bit(IPOIB_PKEY_STOP, &priv->flags); | 449 | set_bit(IPOIB_PKEY_STOP, &priv->flags); |
450 | cancel_delayed_work(&priv->pkey_task); | 450 | cancel_delayed_work(&priv->pkey_task); |
451 | up(&pkey_sem); | 451 | mutex_unlock(&pkey_mutex); |
452 | flush_workqueue(ipoib_workqueue); | 452 | flush_workqueue(ipoib_workqueue); |
453 | } | 453 | } |
454 | 454 | ||
455 | ipoib_mcast_stop_thread(dev, 1); | 455 | ipoib_mcast_stop_thread(dev, 1); |
456 | |||
457 | /* | ||
458 | * Flush the multicast groups first so we stop any multicast joins. The | ||
459 | * completion thread may have already died and we may deadlock waiting | ||
460 | * for the completion thread to finish some multicast joins. | ||
461 | */ | ||
462 | ipoib_mcast_dev_flush(dev); | 456 | ipoib_mcast_dev_flush(dev); |
463 | 457 | ||
464 | /* Delete broadcast and local addresses since they will be recreated */ | ||
465 | ipoib_mcast_dev_down(dev); | ||
466 | |||
467 | ipoib_flush_paths(dev); | 458 | ipoib_flush_paths(dev); |
468 | 459 | ||
469 | return 0; | 460 | return 0; |
@@ -608,13 +599,13 @@ void ipoib_ib_dev_flush(void *_dev) | |||
608 | if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) | 599 | if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) |
609 | ipoib_ib_dev_up(dev); | 600 | ipoib_ib_dev_up(dev); |
610 | 601 | ||
611 | down(&priv->vlan_mutex); | 602 | mutex_lock(&priv->vlan_mutex); |
612 | 603 | ||
613 | /* Flush any child interfaces too */ | 604 | /* Flush any child interfaces too */ |
614 | list_for_each_entry(cpriv, &priv->child_intfs, list) | 605 | list_for_each_entry(cpriv, &priv->child_intfs, list) |
615 | ipoib_ib_dev_flush(&cpriv->dev); | 606 | ipoib_ib_dev_flush(&cpriv->dev); |
616 | 607 | ||
617 | up(&priv->vlan_mutex); | 608 | mutex_unlock(&priv->vlan_mutex); |
618 | } | 609 | } |
619 | 610 | ||
620 | void ipoib_ib_dev_cleanup(struct net_device *dev) | 611 | void ipoib_ib_dev_cleanup(struct net_device *dev) |
@@ -624,9 +615,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) | |||
624 | ipoib_dbg(priv, "cleaning up ib_dev\n"); | 615 | ipoib_dbg(priv, "cleaning up ib_dev\n"); |
625 | 616 | ||
626 | ipoib_mcast_stop_thread(dev, 1); | 617 | ipoib_mcast_stop_thread(dev, 1); |
627 | 618 | ipoib_mcast_dev_flush(dev); | |
628 | /* Delete the broadcast address and the local address */ | ||
629 | ipoib_mcast_dev_down(dev); | ||
630 | 619 | ||
631 | ipoib_transport_dev_cleanup(dev); | 620 | ipoib_transport_dev_cleanup(dev); |
632 | } | 621 | } |
@@ -662,12 +651,12 @@ void ipoib_pkey_poll(void *dev_ptr) | |||
662 | if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) | 651 | if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) |
663 | ipoib_open(dev); | 652 | ipoib_open(dev); |
664 | else { | 653 | else { |
665 | down(&pkey_sem); | 654 | mutex_lock(&pkey_mutex); |
666 | if (!test_bit(IPOIB_PKEY_STOP, &priv->flags)) | 655 | if (!test_bit(IPOIB_PKEY_STOP, &priv->flags)) |
667 | queue_delayed_work(ipoib_workqueue, | 656 | queue_delayed_work(ipoib_workqueue, |
668 | &priv->pkey_task, | 657 | &priv->pkey_task, |
669 | HZ); | 658 | HZ); |
670 | up(&pkey_sem); | 659 | mutex_unlock(&pkey_mutex); |
671 | } | 660 | } |
672 | } | 661 | } |
673 | 662 | ||
@@ -681,12 +670,12 @@ int ipoib_pkey_dev_delay_open(struct net_device *dev) | |||
681 | 670 | ||
682 | /* P_Key value not assigned yet - start polling */ | 671 | /* P_Key value not assigned yet - start polling */ |
683 | if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { | 672 | if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { |
684 | down(&pkey_sem); | 673 | mutex_lock(&pkey_mutex); |
685 | clear_bit(IPOIB_PKEY_STOP, &priv->flags); | 674 | clear_bit(IPOIB_PKEY_STOP, &priv->flags); |
686 | queue_delayed_work(ipoib_workqueue, | 675 | queue_delayed_work(ipoib_workqueue, |
687 | &priv->pkey_task, | 676 | &priv->pkey_task, |
688 | HZ); | 677 | HZ); |
689 | up(&pkey_sem); | 678 | mutex_unlock(&pkey_mutex); |
690 | return 1; | 679 | return 1; |
691 | } | 680 | } |
692 | 681 | ||
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 780009c7eaa6..fd3f5c862a5d 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -105,7 +105,7 @@ int ipoib_open(struct net_device *dev) | |||
105 | struct ipoib_dev_priv *cpriv; | 105 | struct ipoib_dev_priv *cpriv; |
106 | 106 | ||
107 | /* Bring up any child interfaces too */ | 107 | /* Bring up any child interfaces too */ |
108 | down(&priv->vlan_mutex); | 108 | mutex_lock(&priv->vlan_mutex); |
109 | list_for_each_entry(cpriv, &priv->child_intfs, list) { | 109 | list_for_each_entry(cpriv, &priv->child_intfs, list) { |
110 | int flags; | 110 | int flags; |
111 | 111 | ||
@@ -115,7 +115,7 @@ int ipoib_open(struct net_device *dev) | |||
115 | 115 | ||
116 | dev_change_flags(cpriv->dev, flags | IFF_UP); | 116 | dev_change_flags(cpriv->dev, flags | IFF_UP); |
117 | } | 117 | } |
118 | up(&priv->vlan_mutex); | 118 | mutex_unlock(&priv->vlan_mutex); |
119 | } | 119 | } |
120 | 120 | ||
121 | netif_start_queue(dev); | 121 | netif_start_queue(dev); |
@@ -140,7 +140,7 @@ static int ipoib_stop(struct net_device *dev) | |||
140 | struct ipoib_dev_priv *cpriv; | 140 | struct ipoib_dev_priv *cpriv; |
141 | 141 | ||
142 | /* Bring down any child interfaces too */ | 142 | /* Bring down any child interfaces too */ |
143 | down(&priv->vlan_mutex); | 143 | mutex_lock(&priv->vlan_mutex); |
144 | list_for_each_entry(cpriv, &priv->child_intfs, list) { | 144 | list_for_each_entry(cpriv, &priv->child_intfs, list) { |
145 | int flags; | 145 | int flags; |
146 | 146 | ||
@@ -150,7 +150,7 @@ static int ipoib_stop(struct net_device *dev) | |||
150 | 150 | ||
151 | dev_change_flags(cpriv->dev, flags & ~IFF_UP); | 151 | dev_change_flags(cpriv->dev, flags & ~IFF_UP); |
152 | } | 152 | } |
153 | up(&priv->vlan_mutex); | 153 | mutex_unlock(&priv->vlan_mutex); |
154 | } | 154 | } |
155 | 155 | ||
156 | return 0; | 156 | return 0; |
@@ -892,8 +892,8 @@ static void ipoib_setup(struct net_device *dev) | |||
892 | spin_lock_init(&priv->lock); | 892 | spin_lock_init(&priv->lock); |
893 | spin_lock_init(&priv->tx_lock); | 893 | spin_lock_init(&priv->tx_lock); |
894 | 894 | ||
895 | init_MUTEX(&priv->mcast_mutex); | 895 | mutex_init(&priv->mcast_mutex); |
896 | init_MUTEX(&priv->vlan_mutex); | 896 | mutex_init(&priv->vlan_mutex); |
897 | 897 | ||
898 | INIT_LIST_HEAD(&priv->path_list); | 898 | INIT_LIST_HEAD(&priv->path_list); |
899 | INIT_LIST_HEAD(&priv->child_intfs); | 899 | INIT_LIST_HEAD(&priv->child_intfs); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index ed0c2ead8bc1..98039da0caf0 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
@@ -55,7 +55,7 @@ MODULE_PARM_DESC(mcast_debug_level, | |||
55 | "Enable multicast debug tracing if > 0"); | 55 | "Enable multicast debug tracing if > 0"); |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | static DECLARE_MUTEX(mcast_mutex); | 58 | static DEFINE_MUTEX(mcast_mutex); |
59 | 59 | ||
60 | /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */ | 60 | /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */ |
61 | struct ipoib_mcast { | 61 | struct ipoib_mcast { |
@@ -97,8 +97,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) | |||
97 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 97 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
98 | struct ipoib_neigh *neigh, *tmp; | 98 | struct ipoib_neigh *neigh, *tmp; |
99 | unsigned long flags; | 99 | unsigned long flags; |
100 | LIST_HEAD(ah_list); | ||
101 | struct ipoib_ah *ah, *tah; | ||
102 | 100 | ||
103 | ipoib_dbg_mcast(netdev_priv(dev), | 101 | ipoib_dbg_mcast(netdev_priv(dev), |
104 | "deleting multicast group " IPOIB_GID_FMT "\n", | 102 | "deleting multicast group " IPOIB_GID_FMT "\n", |
@@ -107,8 +105,14 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) | |||
107 | spin_lock_irqsave(&priv->lock, flags); | 105 | spin_lock_irqsave(&priv->lock, flags); |
108 | 106 | ||
109 | list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) { | 107 | list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) { |
108 | /* | ||
109 | * It's safe to call ipoib_put_ah() inside priv->lock | ||
110 | * here, because we know that mcast->ah will always | ||
111 | * hold one more reference, so ipoib_put_ah() will | ||
112 | * never do more than decrement the ref count. | ||
113 | */ | ||
110 | if (neigh->ah) | 114 | if (neigh->ah) |
111 | list_add_tail(&neigh->ah->list, &ah_list); | 115 | ipoib_put_ah(neigh->ah); |
112 | *to_ipoib_neigh(neigh->neighbour) = NULL; | 116 | *to_ipoib_neigh(neigh->neighbour) = NULL; |
113 | neigh->neighbour->ops->destructor = NULL; | 117 | neigh->neighbour->ops->destructor = NULL; |
114 | kfree(neigh); | 118 | kfree(neigh); |
@@ -116,9 +120,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) | |||
116 | 120 | ||
117 | spin_unlock_irqrestore(&priv->lock, flags); | 121 | spin_unlock_irqrestore(&priv->lock, flags); |
118 | 122 | ||
119 | list_for_each_entry_safe(ah, tah, &ah_list, list) | ||
120 | ipoib_put_ah(ah); | ||
121 | |||
122 | if (mcast->ah) | 123 | if (mcast->ah) |
123 | ipoib_put_ah(mcast->ah); | 124 | ipoib_put_ah(mcast->ah); |
124 | 125 | ||
@@ -384,10 +385,10 @@ static void ipoib_mcast_join_complete(int status, | |||
384 | 385 | ||
385 | if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) { | 386 | if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) { |
386 | mcast->backoff = 1; | 387 | mcast->backoff = 1; |
387 | down(&mcast_mutex); | 388 | mutex_lock(&mcast_mutex); |
388 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) | 389 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) |
389 | queue_work(ipoib_workqueue, &priv->mcast_task); | 390 | queue_work(ipoib_workqueue, &priv->mcast_task); |
390 | up(&mcast_mutex); | 391 | mutex_unlock(&mcast_mutex); |
391 | complete(&mcast->done); | 392 | complete(&mcast->done); |
392 | return; | 393 | return; |
393 | } | 394 | } |
@@ -417,7 +418,7 @@ static void ipoib_mcast_join_complete(int status, | |||
417 | 418 | ||
418 | mcast->query = NULL; | 419 | mcast->query = NULL; |
419 | 420 | ||
420 | down(&mcast_mutex); | 421 | mutex_lock(&mcast_mutex); |
421 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) { | 422 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) { |
422 | if (status == -ETIMEDOUT) | 423 | if (status == -ETIMEDOUT) |
423 | queue_work(ipoib_workqueue, &priv->mcast_task); | 424 | queue_work(ipoib_workqueue, &priv->mcast_task); |
@@ -426,7 +427,7 @@ static void ipoib_mcast_join_complete(int status, | |||
426 | mcast->backoff * HZ); | 427 | mcast->backoff * HZ); |
427 | } else | 428 | } else |
428 | complete(&mcast->done); | 429 | complete(&mcast->done); |
429 | up(&mcast_mutex); | 430 | mutex_unlock(&mcast_mutex); |
430 | 431 | ||
431 | return; | 432 | return; |
432 | } | 433 | } |
@@ -481,12 +482,12 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast, | |||
481 | if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS) | 482 | if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS) |
482 | mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS; | 483 | mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS; |
483 | 484 | ||
484 | down(&mcast_mutex); | 485 | mutex_lock(&mcast_mutex); |
485 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) | 486 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) |
486 | queue_delayed_work(ipoib_workqueue, | 487 | queue_delayed_work(ipoib_workqueue, |
487 | &priv->mcast_task, | 488 | &priv->mcast_task, |
488 | mcast->backoff * HZ); | 489 | mcast->backoff * HZ); |
489 | up(&mcast_mutex); | 490 | mutex_unlock(&mcast_mutex); |
490 | } else | 491 | } else |
491 | mcast->query_id = ret; | 492 | mcast->query_id = ret; |
492 | } | 493 | } |
@@ -519,11 +520,11 @@ void ipoib_mcast_join_task(void *dev_ptr) | |||
519 | priv->broadcast = ipoib_mcast_alloc(dev, 1); | 520 | priv->broadcast = ipoib_mcast_alloc(dev, 1); |
520 | if (!priv->broadcast) { | 521 | if (!priv->broadcast) { |
521 | ipoib_warn(priv, "failed to allocate broadcast group\n"); | 522 | ipoib_warn(priv, "failed to allocate broadcast group\n"); |
522 | down(&mcast_mutex); | 523 | mutex_lock(&mcast_mutex); |
523 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) | 524 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) |
524 | queue_delayed_work(ipoib_workqueue, | 525 | queue_delayed_work(ipoib_workqueue, |
525 | &priv->mcast_task, HZ); | 526 | &priv->mcast_task, HZ); |
526 | up(&mcast_mutex); | 527 | mutex_unlock(&mcast_mutex); |
527 | return; | 528 | return; |
528 | } | 529 | } |
529 | 530 | ||
@@ -579,10 +580,10 @@ int ipoib_mcast_start_thread(struct net_device *dev) | |||
579 | 580 | ||
580 | ipoib_dbg_mcast(priv, "starting multicast thread\n"); | 581 | ipoib_dbg_mcast(priv, "starting multicast thread\n"); |
581 | 582 | ||
582 | down(&mcast_mutex); | 583 | mutex_lock(&mcast_mutex); |
583 | if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags)) | 584 | if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags)) |
584 | queue_work(ipoib_workqueue, &priv->mcast_task); | 585 | queue_work(ipoib_workqueue, &priv->mcast_task); |
585 | up(&mcast_mutex); | 586 | mutex_unlock(&mcast_mutex); |
586 | 587 | ||
587 | return 0; | 588 | return 0; |
588 | } | 589 | } |
@@ -594,10 +595,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush) | |||
594 | 595 | ||
595 | ipoib_dbg_mcast(priv, "stopping multicast thread\n"); | 596 | ipoib_dbg_mcast(priv, "stopping multicast thread\n"); |
596 | 597 | ||
597 | down(&mcast_mutex); | 598 | mutex_lock(&mcast_mutex); |
598 | clear_bit(IPOIB_MCAST_RUN, &priv->flags); | 599 | clear_bit(IPOIB_MCAST_RUN, &priv->flags); |
599 | cancel_delayed_work(&priv->mcast_task); | 600 | cancel_delayed_work(&priv->mcast_task); |
600 | up(&mcast_mutex); | 601 | mutex_unlock(&mcast_mutex); |
601 | 602 | ||
602 | if (flush) | 603 | if (flush) |
603 | flush_workqueue(ipoib_workqueue); | 604 | flush_workqueue(ipoib_workqueue); |
@@ -741,48 +742,23 @@ void ipoib_mcast_dev_flush(struct net_device *dev) | |||
741 | { | 742 | { |
742 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 743 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
743 | LIST_HEAD(remove_list); | 744 | LIST_HEAD(remove_list); |
744 | struct ipoib_mcast *mcast, *tmcast, *nmcast; | 745 | struct ipoib_mcast *mcast, *tmcast; |
745 | unsigned long flags; | 746 | unsigned long flags; |
746 | 747 | ||
747 | ipoib_dbg_mcast(priv, "flushing multicast list\n"); | 748 | ipoib_dbg_mcast(priv, "flushing multicast list\n"); |
748 | 749 | ||
749 | spin_lock_irqsave(&priv->lock, flags); | 750 | spin_lock_irqsave(&priv->lock, flags); |
750 | list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) { | ||
751 | nmcast = ipoib_mcast_alloc(dev, 0); | ||
752 | if (nmcast) { | ||
753 | nmcast->flags = | ||
754 | mcast->flags & (1 << IPOIB_MCAST_FLAG_SENDONLY); | ||
755 | 751 | ||
756 | nmcast->mcmember.mgid = mcast->mcmember.mgid; | 752 | list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) { |
757 | 753 | list_del(&mcast->list); | |
758 | /* Add the new group in before the to-be-destroyed group */ | 754 | rb_erase(&mcast->rb_node, &priv->multicast_tree); |
759 | list_add_tail(&nmcast->list, &mcast->list); | 755 | list_add_tail(&mcast->list, &remove_list); |
760 | list_del_init(&mcast->list); | ||
761 | |||
762 | rb_replace_node(&mcast->rb_node, &nmcast->rb_node, | ||
763 | &priv->multicast_tree); | ||
764 | |||
765 | list_add_tail(&mcast->list, &remove_list); | ||
766 | } else { | ||
767 | ipoib_warn(priv, "could not reallocate multicast group " | ||
768 | IPOIB_GID_FMT "\n", | ||
769 | IPOIB_GID_ARG(mcast->mcmember.mgid)); | ||
770 | } | ||
771 | } | 756 | } |
772 | 757 | ||
773 | if (priv->broadcast) { | 758 | if (priv->broadcast) { |
774 | nmcast = ipoib_mcast_alloc(dev, 0); | 759 | rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree); |
775 | if (nmcast) { | 760 | list_add_tail(&priv->broadcast->list, &remove_list); |
776 | nmcast->mcmember.mgid = priv->broadcast->mcmember.mgid; | 761 | priv->broadcast = NULL; |
777 | |||
778 | rb_replace_node(&priv->broadcast->rb_node, | ||
779 | &nmcast->rb_node, | ||
780 | &priv->multicast_tree); | ||
781 | |||
782 | list_add_tail(&priv->broadcast->list, &remove_list); | ||
783 | } | ||
784 | |||
785 | priv->broadcast = nmcast; | ||
786 | } | 762 | } |
787 | 763 | ||
788 | spin_unlock_irqrestore(&priv->lock, flags); | 764 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -793,24 +769,6 @@ void ipoib_mcast_dev_flush(struct net_device *dev) | |||
793 | } | 769 | } |
794 | } | 770 | } |
795 | 771 | ||
796 | void ipoib_mcast_dev_down(struct net_device *dev) | ||
797 | { | ||
798 | struct ipoib_dev_priv *priv = netdev_priv(dev); | ||
799 | unsigned long flags; | ||
800 | |||
801 | /* Delete broadcast since it will be recreated */ | ||
802 | if (priv->broadcast) { | ||
803 | ipoib_dbg_mcast(priv, "deleting broadcast group\n"); | ||
804 | |||
805 | spin_lock_irqsave(&priv->lock, flags); | ||
806 | rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree); | ||
807 | spin_unlock_irqrestore(&priv->lock, flags); | ||
808 | ipoib_mcast_leave(dev, priv->broadcast); | ||
809 | ipoib_mcast_free(priv->broadcast); | ||
810 | priv->broadcast = NULL; | ||
811 | } | ||
812 | } | ||
813 | |||
814 | void ipoib_mcast_restart_task(void *dev_ptr) | 772 | void ipoib_mcast_restart_task(void *dev_ptr) |
815 | { | 773 | { |
816 | struct net_device *dev = dev_ptr; | 774 | struct net_device *dev = dev_ptr; |
@@ -824,7 +782,8 @@ void ipoib_mcast_restart_task(void *dev_ptr) | |||
824 | 782 | ||
825 | ipoib_mcast_stop_thread(dev, 0); | 783 | ipoib_mcast_stop_thread(dev, 0); |
826 | 784 | ||
827 | spin_lock_irqsave(&priv->lock, flags); | 785 | spin_lock_irqsave(&dev->xmit_lock, flags); |
786 | spin_lock(&priv->lock); | ||
828 | 787 | ||
829 | /* | 788 | /* |
830 | * Unfortunately, the networking core only gives us a list of all of | 789 | * Unfortunately, the networking core only gives us a list of all of |
@@ -896,7 +855,9 @@ void ipoib_mcast_restart_task(void *dev_ptr) | |||
896 | list_add_tail(&mcast->list, &remove_list); | 855 | list_add_tail(&mcast->list, &remove_list); |
897 | } | 856 | } |
898 | } | 857 | } |
899 | spin_unlock_irqrestore(&priv->lock, flags); | 858 | |
859 | spin_unlock(&priv->lock); | ||
860 | spin_unlock_irqrestore(&dev->xmit_lock, flags); | ||
900 | 861 | ||
901 | /* We have to cancel outside of the spinlock */ | 862 | /* We have to cancel outside of the spinlock */ |
902 | list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { | 863 | list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index e829e10400e3..faaf10e5fc7b 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c | |||
@@ -65,9 +65,9 @@ int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid) | |||
65 | } | 65 | } |
66 | 66 | ||
67 | /* attach QP to multicast group */ | 67 | /* attach QP to multicast group */ |
68 | down(&priv->mcast_mutex); | 68 | mutex_lock(&priv->mcast_mutex); |
69 | ret = ib_attach_mcast(priv->qp, mgid, mlid); | 69 | ret = ib_attach_mcast(priv->qp, mgid, mlid); |
70 | up(&priv->mcast_mutex); | 70 | mutex_unlock(&priv->mcast_mutex); |
71 | if (ret) | 71 | if (ret) |
72 | ipoib_warn(priv, "failed to attach to multicast group, ret = %d\n", ret); | 72 | ipoib_warn(priv, "failed to attach to multicast group, ret = %d\n", ret); |
73 | 73 | ||
@@ -81,9 +81,9 @@ int ipoib_mcast_detach(struct net_device *dev, u16 mlid, union ib_gid *mgid) | |||
81 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 81 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
82 | int ret; | 82 | int ret; |
83 | 83 | ||
84 | down(&priv->mcast_mutex); | 84 | mutex_lock(&priv->mcast_mutex); |
85 | ret = ib_detach_mcast(priv->qp, mgid, mlid); | 85 | ret = ib_detach_mcast(priv->qp, mgid, mlid); |
86 | up(&priv->mcast_mutex); | 86 | mutex_unlock(&priv->mcast_mutex); |
87 | if (ret) | 87 | if (ret) |
88 | ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret); | 88 | ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret); |
89 | 89 | ||
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index d280b341a37f..4ca175553f9f 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c | |||
@@ -63,7 +63,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) | |||
63 | 63 | ||
64 | ppriv = netdev_priv(pdev); | 64 | ppriv = netdev_priv(pdev); |
65 | 65 | ||
66 | down(&ppriv->vlan_mutex); | 66 | mutex_lock(&ppriv->vlan_mutex); |
67 | 67 | ||
68 | /* | 68 | /* |
69 | * First ensure this isn't a duplicate. We check the parent device and | 69 | * First ensure this isn't a duplicate. We check the parent device and |
@@ -124,7 +124,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) | |||
124 | 124 | ||
125 | list_add_tail(&priv->list, &ppriv->child_intfs); | 125 | list_add_tail(&priv->list, &ppriv->child_intfs); |
126 | 126 | ||
127 | up(&ppriv->vlan_mutex); | 127 | mutex_unlock(&ppriv->vlan_mutex); |
128 | 128 | ||
129 | return 0; | 129 | return 0; |
130 | 130 | ||
@@ -139,7 +139,7 @@ device_init_failed: | |||
139 | free_netdev(priv->dev); | 139 | free_netdev(priv->dev); |
140 | 140 | ||
141 | err: | 141 | err: |
142 | up(&ppriv->vlan_mutex); | 142 | mutex_unlock(&ppriv->vlan_mutex); |
143 | return result; | 143 | return result; |
144 | } | 144 | } |
145 | 145 | ||
@@ -153,7 +153,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) | |||
153 | 153 | ||
154 | ppriv = netdev_priv(pdev); | 154 | ppriv = netdev_priv(pdev); |
155 | 155 | ||
156 | down(&ppriv->vlan_mutex); | 156 | mutex_lock(&ppriv->vlan_mutex); |
157 | list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { | 157 | list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { |
158 | if (priv->pkey == pkey) { | 158 | if (priv->pkey == pkey) { |
159 | unregister_netdev(priv->dev); | 159 | unregister_netdev(priv->dev); |
@@ -167,7 +167,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) | |||
167 | break; | 167 | break; |
168 | } | 168 | } |
169 | } | 169 | } |
170 | up(&ppriv->vlan_mutex); | 170 | mutex_unlock(&ppriv->vlan_mutex); |
171 | 171 | ||
172 | return ret; | 172 | return ret; |
173 | } | 173 | } |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index dd488d3cffa9..31207e664148 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -1516,8 +1516,7 @@ static ssize_t show_port(struct class_device *class_dev, char *buf) | |||
1516 | 1516 | ||
1517 | static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL); | 1517 | static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL); |
1518 | 1518 | ||
1519 | static struct srp_host *srp_add_port(struct ib_device *device, | 1519 | static struct srp_host *srp_add_port(struct ib_device *device, u8 port) |
1520 | __be64 node_guid, u8 port) | ||
1521 | { | 1520 | { |
1522 | struct srp_host *host; | 1521 | struct srp_host *host; |
1523 | 1522 | ||
@@ -1532,7 +1531,7 @@ static struct srp_host *srp_add_port(struct ib_device *device, | |||
1532 | host->port = port; | 1531 | host->port = port; |
1533 | 1532 | ||
1534 | host->initiator_port_id[7] = port; | 1533 | host->initiator_port_id[7] = port; |
1535 | memcpy(host->initiator_port_id + 8, &node_guid, 8); | 1534 | memcpy(host->initiator_port_id + 8, &device->node_guid, 8); |
1536 | 1535 | ||
1537 | host->pd = ib_alloc_pd(device); | 1536 | host->pd = ib_alloc_pd(device); |
1538 | if (IS_ERR(host->pd)) | 1537 | if (IS_ERR(host->pd)) |
@@ -1580,22 +1579,11 @@ static void srp_add_one(struct ib_device *device) | |||
1580 | { | 1579 | { |
1581 | struct list_head *dev_list; | 1580 | struct list_head *dev_list; |
1582 | struct srp_host *host; | 1581 | struct srp_host *host; |
1583 | struct ib_device_attr *dev_attr; | ||
1584 | int s, e, p; | 1582 | int s, e, p; |
1585 | 1583 | ||
1586 | dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL); | ||
1587 | if (!dev_attr) | ||
1588 | return; | ||
1589 | |||
1590 | if (ib_query_device(device, dev_attr)) { | ||
1591 | printk(KERN_WARNING PFX "Couldn't query node GUID for %s.\n", | ||
1592 | device->name); | ||
1593 | goto out; | ||
1594 | } | ||
1595 | |||
1596 | dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); | 1584 | dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); |
1597 | if (!dev_list) | 1585 | if (!dev_list) |
1598 | goto out; | 1586 | return; |
1599 | 1587 | ||
1600 | INIT_LIST_HEAD(dev_list); | 1588 | INIT_LIST_HEAD(dev_list); |
1601 | 1589 | ||
@@ -1608,15 +1596,12 @@ static void srp_add_one(struct ib_device *device) | |||
1608 | } | 1596 | } |
1609 | 1597 | ||
1610 | for (p = s; p <= e; ++p) { | 1598 | for (p = s; p <= e; ++p) { |
1611 | host = srp_add_port(device, dev_attr->node_guid, p); | 1599 | host = srp_add_port(device, p); |
1612 | if (host) | 1600 | if (host) |
1613 | list_add_tail(&host->list, dev_list); | 1601 | list_add_tail(&host->list, dev_list); |
1614 | } | 1602 | } |
1615 | 1603 | ||
1616 | ib_set_client_data(device, &srp_client, dev_list); | 1604 | ib_set_client_data(device, &srp_client, dev_list); |
1617 | |||
1618 | out: | ||
1619 | kfree(dev_attr); | ||
1620 | } | 1605 | } |
1621 | 1606 | ||
1622 | static void srp_remove_one(struct ib_device *device) | 1607 | static void srp_remove_one(struct ib_device *device) |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 24474335dfd1..2141501e9f2e 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -348,6 +348,40 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) | |||
348 | return 0; | 348 | return 0; |
349 | } | 349 | } |
350 | 350 | ||
351 | /* | ||
352 | * alps_poll() - poll the touchpad for current motion packet. | ||
353 | * Used in resync. | ||
354 | */ | ||
355 | static int alps_poll(struct psmouse *psmouse) | ||
356 | { | ||
357 | struct alps_data *priv = psmouse->private; | ||
358 | unsigned char buf[6]; | ||
359 | int poll_failed; | ||
360 | |||
361 | if (priv->i->flags & ALPS_PASS) | ||
362 | alps_passthrough_mode(psmouse, 1); | ||
363 | |||
364 | poll_failed = ps2_command(&psmouse->ps2dev, buf, | ||
365 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; | ||
366 | |||
367 | if (priv->i->flags & ALPS_PASS) | ||
368 | alps_passthrough_mode(psmouse, 0); | ||
369 | |||
370 | if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) | ||
371 | return -1; | ||
372 | |||
373 | if ((psmouse->badbyte & 0xc8) == 0x08) { | ||
374 | /* | ||
375 | * Poll the track stick ... | ||
376 | */ | ||
377 | if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8))) | ||
378 | return -1; | ||
379 | } | ||
380 | |||
381 | memcpy(psmouse->packet, buf, sizeof(buf)); | ||
382 | return 0; | ||
383 | } | ||
384 | |||
351 | static int alps_reconnect(struct psmouse *psmouse) | 385 | static int alps_reconnect(struct psmouse *psmouse) |
352 | { | 386 | { |
353 | struct alps_data *priv = psmouse->private; | 387 | struct alps_data *priv = psmouse->private; |
@@ -451,10 +485,14 @@ int alps_init(struct psmouse *psmouse) | |||
451 | input_register_device(priv->dev2); | 485 | input_register_device(priv->dev2); |
452 | 486 | ||
453 | psmouse->protocol_handler = alps_process_byte; | 487 | psmouse->protocol_handler = alps_process_byte; |
488 | psmouse->poll = alps_poll; | ||
454 | psmouse->disconnect = alps_disconnect; | 489 | psmouse->disconnect = alps_disconnect; |
455 | psmouse->reconnect = alps_reconnect; | 490 | psmouse->reconnect = alps_reconnect; |
456 | psmouse->pktsize = 6; | 491 | psmouse->pktsize = 6; |
457 | 492 | ||
493 | /* We are having trouble resyncing ALPS touchpads so disable it for now */ | ||
494 | psmouse->resync_time = 0; | ||
495 | |||
458 | return 0; | 496 | return 0; |
459 | 497 | ||
460 | init_fail: | 498 | init_fail: |
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 025a71de5404..c88520d3d13c 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c | |||
@@ -117,7 +117,7 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha | |||
117 | if (psmouse_sliced_command(psmouse, command)) | 117 | if (psmouse_sliced_command(psmouse, command)) |
118 | return -1; | 118 | return -1; |
119 | 119 | ||
120 | if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL)) | 120 | if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL | 0x0300)) |
121 | return -1; | 121 | return -1; |
122 | 122 | ||
123 | return 0; | 123 | return 0; |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 4d5ecc04c5b6..7665fd9ce559 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -54,10 +54,14 @@ static unsigned int psmouse_smartscroll = 1; | |||
54 | module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); | 54 | module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); |
55 | MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); | 55 | MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); |
56 | 56 | ||
57 | static unsigned int psmouse_resetafter; | 57 | static unsigned int psmouse_resetafter = 5; |
58 | module_param_named(resetafter, psmouse_resetafter, uint, 0644); | 58 | module_param_named(resetafter, psmouse_resetafter, uint, 0644); |
59 | MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); | 59 | MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); |
60 | 60 | ||
61 | static unsigned int psmouse_resync_time = 5; | ||
62 | module_param_named(resync_time, psmouse_resync_time, uint, 0644); | ||
63 | MODULE_PARM_DESC(resync_time, "How long can mouse stay idle before forcing resync (in seconds, 0 = never)."); | ||
64 | |||
61 | PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO, | 65 | PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO, |
62 | NULL, | 66 | NULL, |
63 | psmouse_attr_show_protocol, psmouse_attr_set_protocol); | 67 | psmouse_attr_show_protocol, psmouse_attr_set_protocol); |
@@ -70,12 +74,16 @@ PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO, | |||
70 | PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO, | 74 | PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO, |
71 | (void *) offsetof(struct psmouse, resetafter), | 75 | (void *) offsetof(struct psmouse, resetafter), |
72 | psmouse_show_int_attr, psmouse_set_int_attr); | 76 | psmouse_show_int_attr, psmouse_set_int_attr); |
77 | PSMOUSE_DEFINE_ATTR(resync_time, S_IWUSR | S_IRUGO, | ||
78 | (void *) offsetof(struct psmouse, resync_time), | ||
79 | psmouse_show_int_attr, psmouse_set_int_attr); | ||
73 | 80 | ||
74 | static struct attribute *psmouse_attributes[] = { | 81 | static struct attribute *psmouse_attributes[] = { |
75 | &psmouse_attr_protocol.dattr.attr, | 82 | &psmouse_attr_protocol.dattr.attr, |
76 | &psmouse_attr_rate.dattr.attr, | 83 | &psmouse_attr_rate.dattr.attr, |
77 | &psmouse_attr_resolution.dattr.attr, | 84 | &psmouse_attr_resolution.dattr.attr, |
78 | &psmouse_attr_resetafter.dattr.attr, | 85 | &psmouse_attr_resetafter.dattr.attr, |
86 | &psmouse_attr_resync_time.dattr.attr, | ||
79 | NULL | 87 | NULL |
80 | }; | 88 | }; |
81 | 89 | ||
@@ -98,6 +106,8 @@ __obsolete_setup("psmouse_rate="); | |||
98 | */ | 106 | */ |
99 | static DECLARE_MUTEX(psmouse_sem); | 107 | static DECLARE_MUTEX(psmouse_sem); |
100 | 108 | ||
109 | static struct workqueue_struct *kpsmoused_wq; | ||
110 | |||
101 | struct psmouse_protocol { | 111 | struct psmouse_protocol { |
102 | enum psmouse_type type; | 112 | enum psmouse_type type; |
103 | char *name; | 113 | char *name; |
@@ -178,15 +188,79 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_reg | |||
178 | } | 188 | } |
179 | 189 | ||
180 | /* | 190 | /* |
181 | * psmouse_interrupt() handles incoming characters, either gathering them into | 191 | * __psmouse_set_state() sets new psmouse state and resets all flags. |
182 | * packets or passing them to the command routine as command output. | 192 | */ |
193 | |||
194 | static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | ||
195 | { | ||
196 | psmouse->state = new_state; | ||
197 | psmouse->pktcnt = psmouse->out_of_sync = 0; | ||
198 | psmouse->ps2dev.flags = 0; | ||
199 | psmouse->last = jiffies; | ||
200 | } | ||
201 | |||
202 | |||
203 | /* | ||
204 | * psmouse_set_state() sets new psmouse state and resets all flags and | ||
205 | * counters while holding serio lock so fighting with interrupt handler | ||
206 | * is not a concern. | ||
207 | */ | ||
208 | |||
209 | static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | ||
210 | { | ||
211 | serio_pause_rx(psmouse->ps2dev.serio); | ||
212 | __psmouse_set_state(psmouse, new_state); | ||
213 | serio_continue_rx(psmouse->ps2dev.serio); | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * psmouse_handle_byte() processes one byte of the input data stream | ||
218 | * by calling corresponding protocol handler. | ||
219 | */ | ||
220 | |||
221 | static int psmouse_handle_byte(struct psmouse *psmouse, struct pt_regs *regs) | ||
222 | { | ||
223 | psmouse_ret_t rc = psmouse->protocol_handler(psmouse, regs); | ||
224 | |||
225 | switch (rc) { | ||
226 | case PSMOUSE_BAD_DATA: | ||
227 | if (psmouse->state == PSMOUSE_ACTIVATED) { | ||
228 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", | ||
229 | psmouse->name, psmouse->phys, psmouse->pktcnt); | ||
230 | if (++psmouse->out_of_sync == psmouse->resetafter) { | ||
231 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
232 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); | ||
233 | serio_reconnect(psmouse->ps2dev.serio); | ||
234 | return -1; | ||
235 | } | ||
236 | } | ||
237 | psmouse->pktcnt = 0; | ||
238 | break; | ||
239 | |||
240 | case PSMOUSE_FULL_PACKET: | ||
241 | psmouse->pktcnt = 0; | ||
242 | if (psmouse->out_of_sync) { | ||
243 | psmouse->out_of_sync = 0; | ||
244 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | ||
245 | psmouse->name, psmouse->phys); | ||
246 | } | ||
247 | break; | ||
248 | |||
249 | case PSMOUSE_GOOD_DATA: | ||
250 | break; | ||
251 | } | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | /* | ||
256 | * psmouse_interrupt() handles incoming characters, either passing them | ||
257 | * for normal processing or gathering them as command response. | ||
183 | */ | 258 | */ |
184 | 259 | ||
185 | static irqreturn_t psmouse_interrupt(struct serio *serio, | 260 | static irqreturn_t psmouse_interrupt(struct serio *serio, |
186 | unsigned char data, unsigned int flags, struct pt_regs *regs) | 261 | unsigned char data, unsigned int flags, struct pt_regs *regs) |
187 | { | 262 | { |
188 | struct psmouse *psmouse = serio_get_drvdata(serio); | 263 | struct psmouse *psmouse = serio_get_drvdata(serio); |
189 | psmouse_ret_t rc; | ||
190 | 264 | ||
191 | if (psmouse->state == PSMOUSE_IGNORE) | 265 | if (psmouse->state == PSMOUSE_IGNORE) |
192 | goto out; | 266 | goto out; |
@@ -208,67 +282,58 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
208 | if (ps2_handle_response(&psmouse->ps2dev, data)) | 282 | if (ps2_handle_response(&psmouse->ps2dev, data)) |
209 | goto out; | 283 | goto out; |
210 | 284 | ||
211 | if (psmouse->state == PSMOUSE_INITIALIZING) | 285 | if (psmouse->state <= PSMOUSE_RESYNCING) |
212 | goto out; | 286 | goto out; |
213 | 287 | ||
214 | if (psmouse->state == PSMOUSE_ACTIVATED && | 288 | if (psmouse->state == PSMOUSE_ACTIVATED && |
215 | psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { | 289 | psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { |
216 | printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", | 290 | printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", |
217 | psmouse->name, psmouse->phys, psmouse->pktcnt); | 291 | psmouse->name, psmouse->phys, psmouse->pktcnt); |
218 | psmouse->pktcnt = 0; | 292 | psmouse->badbyte = psmouse->packet[0]; |
293 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | ||
294 | queue_work(kpsmoused_wq, &psmouse->resync_work); | ||
295 | goto out; | ||
219 | } | 296 | } |
220 | 297 | ||
221 | psmouse->last = jiffies; | ||
222 | psmouse->packet[psmouse->pktcnt++] = data; | 298 | psmouse->packet[psmouse->pktcnt++] = data; |
223 | 299 | /* | |
224 | if (psmouse->packet[0] == PSMOUSE_RET_BAT) { | 300 | * Check if this is a new device announcement (0xAA 0x00) |
301 | */ | ||
302 | if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) { | ||
225 | if (psmouse->pktcnt == 1) | 303 | if (psmouse->pktcnt == 1) |
226 | goto out; | 304 | goto out; |
227 | 305 | ||
228 | if (psmouse->pktcnt == 2) { | 306 | if (psmouse->packet[1] == PSMOUSE_RET_ID) { |
229 | if (psmouse->packet[1] == PSMOUSE_RET_ID) { | 307 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
230 | psmouse->state = PSMOUSE_IGNORE; | 308 | serio_reconnect(serio); |
231 | serio_reconnect(serio); | 309 | goto out; |
232 | goto out; | ||
233 | } | ||
234 | if (psmouse->type == PSMOUSE_SYNAPTICS) { | ||
235 | /* neither 0xAA nor 0x00 are valid first bytes | ||
236 | * for a packet in absolute mode | ||
237 | */ | ||
238 | psmouse->pktcnt = 0; | ||
239 | goto out; | ||
240 | } | ||
241 | } | 310 | } |
242 | } | 311 | /* |
243 | 312 | * Not a new device, try processing first byte normally | |
244 | rc = psmouse->protocol_handler(psmouse, regs); | 313 | */ |
314 | psmouse->pktcnt = 1; | ||
315 | if (psmouse_handle_byte(psmouse, regs)) | ||
316 | goto out; | ||
245 | 317 | ||
246 | switch (rc) { | 318 | psmouse->packet[psmouse->pktcnt++] = data; |
247 | case PSMOUSE_BAD_DATA: | 319 | } |
248 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", | ||
249 | psmouse->name, psmouse->phys, psmouse->pktcnt); | ||
250 | psmouse->pktcnt = 0; | ||
251 | 320 | ||
252 | if (++psmouse->out_of_sync == psmouse->resetafter) { | 321 | /* |
253 | psmouse->state = PSMOUSE_IGNORE; | 322 | * See if we need to force resync because mouse was idle for too long |
254 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); | 323 | */ |
255 | serio_reconnect(psmouse->ps2dev.serio); | 324 | if (psmouse->state == PSMOUSE_ACTIVATED && |
256 | } | 325 | psmouse->pktcnt == 1 && psmouse->resync_time && |
257 | break; | 326 | time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) { |
327 | psmouse->badbyte = psmouse->packet[0]; | ||
328 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | ||
329 | queue_work(kpsmoused_wq, &psmouse->resync_work); | ||
330 | goto out; | ||
331 | } | ||
258 | 332 | ||
259 | case PSMOUSE_FULL_PACKET: | 333 | psmouse->last = jiffies; |
260 | psmouse->pktcnt = 0; | 334 | psmouse_handle_byte(psmouse, regs); |
261 | if (psmouse->out_of_sync) { | ||
262 | psmouse->out_of_sync = 0; | ||
263 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | ||
264 | psmouse->name, psmouse->phys); | ||
265 | } | ||
266 | break; | ||
267 | 335 | ||
268 | case PSMOUSE_GOOD_DATA: | 336 | out: |
269 | break; | ||
270 | } | ||
271 | out: | ||
272 | return IRQ_HANDLED; | 337 | return IRQ_HANDLED; |
273 | } | 338 | } |
274 | 339 | ||
@@ -752,21 +817,6 @@ static void psmouse_initialize(struct psmouse *psmouse) | |||
752 | } | 817 | } |
753 | 818 | ||
754 | /* | 819 | /* |
755 | * psmouse_set_state() sets new psmouse state and resets all flags and | ||
756 | * counters while holding serio lock so fighting with interrupt handler | ||
757 | * is not a concern. | ||
758 | */ | ||
759 | |||
760 | static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | ||
761 | { | ||
762 | serio_pause_rx(psmouse->ps2dev.serio); | ||
763 | psmouse->state = new_state; | ||
764 | psmouse->pktcnt = psmouse->out_of_sync = 0; | ||
765 | psmouse->ps2dev.flags = 0; | ||
766 | serio_continue_rx(psmouse->ps2dev.serio); | ||
767 | } | ||
768 | |||
769 | /* | ||
770 | * psmouse_activate() enables the mouse so that we get motion reports from it. | 820 | * psmouse_activate() enables the mouse so that we get motion reports from it. |
771 | */ | 821 | */ |
772 | 822 | ||
@@ -794,6 +844,111 @@ static void psmouse_deactivate(struct psmouse *psmouse) | |||
794 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 844 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
795 | } | 845 | } |
796 | 846 | ||
847 | /* | ||
848 | * psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it. | ||
849 | */ | ||
850 | |||
851 | static int psmouse_poll(struct psmouse *psmouse) | ||
852 | { | ||
853 | return ps2_command(&psmouse->ps2dev, psmouse->packet, | ||
854 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)); | ||
855 | } | ||
856 | |||
857 | |||
858 | /* | ||
859 | * psmouse_resync() attempts to re-validate current protocol. | ||
860 | */ | ||
861 | |||
862 | static void psmouse_resync(void *p) | ||
863 | { | ||
864 | struct psmouse *psmouse = p, *parent = NULL; | ||
865 | struct serio *serio = psmouse->ps2dev.serio; | ||
866 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; | ||
867 | int failed = 0, enabled = 0; | ||
868 | int i; | ||
869 | |||
870 | down(&psmouse_sem); | ||
871 | |||
872 | if (psmouse->state != PSMOUSE_RESYNCING) | ||
873 | goto out; | ||
874 | |||
875 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | ||
876 | parent = serio_get_drvdata(serio->parent); | ||
877 | psmouse_deactivate(parent); | ||
878 | } | ||
879 | |||
880 | /* | ||
881 | * Some mice don't ACK commands sent while they are in the middle of | ||
882 | * transmitting motion packet. To avoid delay we use ps2_sendbyte() | ||
883 | * instead of ps2_command() which would wait for 200ms for an ACK | ||
884 | * that may never come. | ||
885 | * As an additional quirk ALPS touchpads may not only forget to ACK | ||
886 | * disable command but will stop reporting taps, so if we see that | ||
887 | * mouse at least once ACKs disable we will do full reconnect if ACK | ||
888 | * is missing. | ||
889 | */ | ||
890 | psmouse->num_resyncs++; | ||
891 | |||
892 | if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) { | ||
893 | if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command) | ||
894 | failed = 1; | ||
895 | } else | ||
896 | psmouse->acks_disable_command = 1; | ||
897 | |||
898 | /* | ||
899 | * Poll the mouse. If it was reset the packet will be shorter than | ||
900 | * psmouse->pktsize and ps2_command will fail. We do not expect and | ||
901 | * do not handle scenario when mouse "upgrades" its protocol while | ||
902 | * disconnected since it would require additional delay. If we ever | ||
903 | * see a mouse that does it we'll adjust the code. | ||
904 | */ | ||
905 | if (!failed) { | ||
906 | if (psmouse->poll(psmouse)) | ||
907 | failed = 1; | ||
908 | else { | ||
909 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
910 | for (i = 0; i < psmouse->pktsize; i++) { | ||
911 | psmouse->pktcnt++; | ||
912 | rc = psmouse->protocol_handler(psmouse, NULL); | ||
913 | if (rc != PSMOUSE_GOOD_DATA) | ||
914 | break; | ||
915 | } | ||
916 | if (rc != PSMOUSE_FULL_PACKET) | ||
917 | failed = 1; | ||
918 | psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | ||
919 | } | ||
920 | } | ||
921 | /* | ||
922 | * Now try to enable mouse. We try to do that even if poll failed and also | ||
923 | * repeat our attempts 5 times, otherwise we may be left out with disabled | ||
924 | * mouse. | ||
925 | */ | ||
926 | for (i = 0; i < 5; i++) { | ||
927 | if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { | ||
928 | enabled = 1; | ||
929 | break; | ||
930 | } | ||
931 | msleep(200); | ||
932 | } | ||
933 | |||
934 | if (!enabled) { | ||
935 | printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n", | ||
936 | psmouse->ps2dev.serio->phys); | ||
937 | failed = 1; | ||
938 | } | ||
939 | |||
940 | if (failed) { | ||
941 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
942 | printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n"); | ||
943 | serio_reconnect(serio); | ||
944 | } else | ||
945 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
946 | |||
947 | if (parent) | ||
948 | psmouse_activate(parent); | ||
949 | out: | ||
950 | up(&psmouse_sem); | ||
951 | } | ||
797 | 952 | ||
798 | /* | 953 | /* |
799 | * psmouse_cleanup() resets the mouse into power-on state. | 954 | * psmouse_cleanup() resets the mouse into power-on state. |
@@ -822,6 +977,11 @@ static void psmouse_disconnect(struct serio *serio) | |||
822 | 977 | ||
823 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 978 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
824 | 979 | ||
980 | /* make sure we don't have a resync in progress */ | ||
981 | up(&psmouse_sem); | ||
982 | flush_workqueue(kpsmoused_wq); | ||
983 | down(&psmouse_sem); | ||
984 | |||
825 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 985 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
826 | parent = serio_get_drvdata(serio->parent); | 986 | parent = serio_get_drvdata(serio->parent); |
827 | psmouse_deactivate(parent); | 987 | psmouse_deactivate(parent); |
@@ -859,6 +1019,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto | |||
859 | 1019 | ||
860 | psmouse->set_rate = psmouse_set_rate; | 1020 | psmouse->set_rate = psmouse_set_rate; |
861 | psmouse->set_resolution = psmouse_set_resolution; | 1021 | psmouse->set_resolution = psmouse_set_resolution; |
1022 | psmouse->poll = psmouse_poll; | ||
862 | psmouse->protocol_handler = psmouse_process_byte; | 1023 | psmouse->protocol_handler = psmouse_process_byte; |
863 | psmouse->pktsize = 3; | 1024 | psmouse->pktsize = 3; |
864 | 1025 | ||
@@ -874,6 +1035,23 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto | |||
874 | else | 1035 | else |
875 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); | 1036 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); |
876 | 1037 | ||
1038 | /* | ||
1039 | * If mouse's packet size is 3 there is no point in polling the | ||
1040 | * device in hopes to detect protocol reset - we won't get less | ||
1041 | * than 3 bytes response anyhow. | ||
1042 | */ | ||
1043 | if (psmouse->pktsize == 3) | ||
1044 | psmouse->resync_time = 0; | ||
1045 | |||
1046 | /* | ||
1047 | * Some smart KVMs fake response to POLL command returning just | ||
1048 | * 3 bytes and messing up our resync logic, so if initial poll | ||
1049 | * fails we won't try polling the device anymore. Hopefully | ||
1050 | * such KVM will maintain initially selected protocol. | ||
1051 | */ | ||
1052 | if (psmouse->resync_time && psmouse->poll(psmouse)) | ||
1053 | psmouse->resync_time = 0; | ||
1054 | |||
877 | sprintf(psmouse->devname, "%s %s %s", | 1055 | sprintf(psmouse->devname, "%s %s %s", |
878 | psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); | 1056 | psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); |
879 | 1057 | ||
@@ -914,6 +1092,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
914 | goto out; | 1092 | goto out; |
915 | 1093 | ||
916 | ps2_init(&psmouse->ps2dev, serio); | 1094 | ps2_init(&psmouse->ps2dev, serio); |
1095 | INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse); | ||
917 | psmouse->dev = input_dev; | 1096 | psmouse->dev = input_dev; |
918 | sprintf(psmouse->phys, "%s/input0", serio->phys); | 1097 | sprintf(psmouse->phys, "%s/input0", serio->phys); |
919 | 1098 | ||
@@ -934,6 +1113,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
934 | psmouse->rate = psmouse_rate; | 1113 | psmouse->rate = psmouse_rate; |
935 | psmouse->resolution = psmouse_resolution; | 1114 | psmouse->resolution = psmouse_resolution; |
936 | psmouse->resetafter = psmouse_resetafter; | 1115 | psmouse->resetafter = psmouse_resetafter; |
1116 | psmouse->resync_time = parent ? 0 : psmouse_resync_time; | ||
937 | psmouse->smartscroll = psmouse_smartscroll; | 1117 | psmouse->smartscroll = psmouse_smartscroll; |
938 | 1118 | ||
939 | psmouse_switch_protocol(psmouse, NULL); | 1119 | psmouse_switch_protocol(psmouse, NULL); |
@@ -1278,13 +1458,21 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) | |||
1278 | 1458 | ||
1279 | static int __init psmouse_init(void) | 1459 | static int __init psmouse_init(void) |
1280 | { | 1460 | { |
1461 | kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); | ||
1462 | if (!kpsmoused_wq) { | ||
1463 | printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n"); | ||
1464 | return -ENOMEM; | ||
1465 | } | ||
1466 | |||
1281 | serio_register_driver(&psmouse_drv); | 1467 | serio_register_driver(&psmouse_drv); |
1468 | |||
1282 | return 0; | 1469 | return 0; |
1283 | } | 1470 | } |
1284 | 1471 | ||
1285 | static void __exit psmouse_exit(void) | 1472 | static void __exit psmouse_exit(void) |
1286 | { | 1473 | { |
1287 | serio_unregister_driver(&psmouse_drv); | 1474 | serio_unregister_driver(&psmouse_drv); |
1475 | destroy_workqueue(kpsmoused_wq); | ||
1288 | } | 1476 | } |
1289 | 1477 | ||
1290 | module_init(psmouse_init); | 1478 | module_init(psmouse_init); |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 7c4192bd1279..4d9107fba6a1 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
@@ -7,7 +7,7 @@ | |||
7 | #define PSMOUSE_CMD_GETINFO 0x03e9 | 7 | #define PSMOUSE_CMD_GETINFO 0x03e9 |
8 | #define PSMOUSE_CMD_SETSTREAM 0x00ea | 8 | #define PSMOUSE_CMD_SETSTREAM 0x00ea |
9 | #define PSMOUSE_CMD_SETPOLL 0x00f0 | 9 | #define PSMOUSE_CMD_SETPOLL 0x00f0 |
10 | #define PSMOUSE_CMD_POLL 0x03eb | 10 | #define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */ |
11 | #define PSMOUSE_CMD_GETID 0x02f2 | 11 | #define PSMOUSE_CMD_GETID 0x02f2 |
12 | #define PSMOUSE_CMD_SETRATE 0x10f3 | 12 | #define PSMOUSE_CMD_SETRATE 0x10f3 |
13 | #define PSMOUSE_CMD_ENABLE 0x00f4 | 13 | #define PSMOUSE_CMD_ENABLE 0x00f4 |
@@ -23,6 +23,7 @@ | |||
23 | enum psmouse_state { | 23 | enum psmouse_state { |
24 | PSMOUSE_IGNORE, | 24 | PSMOUSE_IGNORE, |
25 | PSMOUSE_INITIALIZING, | 25 | PSMOUSE_INITIALIZING, |
26 | PSMOUSE_RESYNCING, | ||
26 | PSMOUSE_CMD_MODE, | 27 | PSMOUSE_CMD_MODE, |
27 | PSMOUSE_ACTIVATED, | 28 | PSMOUSE_ACTIVATED, |
28 | }; | 29 | }; |
@@ -38,15 +39,19 @@ struct psmouse { | |||
38 | void *private; | 39 | void *private; |
39 | struct input_dev *dev; | 40 | struct input_dev *dev; |
40 | struct ps2dev ps2dev; | 41 | struct ps2dev ps2dev; |
42 | struct work_struct resync_work; | ||
41 | char *vendor; | 43 | char *vendor; |
42 | char *name; | 44 | char *name; |
43 | unsigned char packet[8]; | 45 | unsigned char packet[8]; |
46 | unsigned char badbyte; | ||
44 | unsigned char pktcnt; | 47 | unsigned char pktcnt; |
45 | unsigned char pktsize; | 48 | unsigned char pktsize; |
46 | unsigned char type; | 49 | unsigned char type; |
50 | unsigned char acks_disable_command; | ||
47 | unsigned int model; | 51 | unsigned int model; |
48 | unsigned long last; | 52 | unsigned long last; |
49 | unsigned long out_of_sync; | 53 | unsigned long out_of_sync; |
54 | unsigned long num_resyncs; | ||
50 | enum psmouse_state state; | 55 | enum psmouse_state state; |
51 | char devname[64]; | 56 | char devname[64]; |
52 | char phys[32]; | 57 | char phys[32]; |
@@ -54,6 +59,7 @@ struct psmouse { | |||
54 | unsigned int rate; | 59 | unsigned int rate; |
55 | unsigned int resolution; | 60 | unsigned int resolution; |
56 | unsigned int resetafter; | 61 | unsigned int resetafter; |
62 | unsigned int resync_time; | ||
57 | unsigned int smartscroll; /* Logitech only */ | 63 | unsigned int smartscroll; /* Logitech only */ |
58 | 64 | ||
59 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); | 65 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); |
@@ -62,6 +68,7 @@ struct psmouse { | |||
62 | 68 | ||
63 | int (*reconnect)(struct psmouse *psmouse); | 69 | int (*reconnect)(struct psmouse *psmouse); |
64 | void (*disconnect)(struct psmouse *psmouse); | 70 | void (*disconnect)(struct psmouse *psmouse); |
71 | int (*poll)(struct psmouse *psmouse); | ||
65 | 72 | ||
66 | void (*pt_activate)(struct psmouse *psmouse); | 73 | void (*pt_activate)(struct psmouse *psmouse); |
67 | void (*pt_deactivate)(struct psmouse *psmouse); | 74 | void (*pt_deactivate)(struct psmouse *psmouse); |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 97cdfd6acaca..2051bec2c394 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -652,6 +652,8 @@ int synaptics_init(struct psmouse *psmouse) | |||
652 | psmouse->disconnect = synaptics_disconnect; | 652 | psmouse->disconnect = synaptics_disconnect; |
653 | psmouse->reconnect = synaptics_reconnect; | 653 | psmouse->reconnect = synaptics_reconnect; |
654 | psmouse->pktsize = 6; | 654 | psmouse->pktsize = 6; |
655 | /* Synaptics can usually stay in sync without extra help */ | ||
656 | psmouse->resync_time = 0; | ||
655 | 657 | ||
656 | if (SYN_CAP_PASS_THROUGH(priv->capabilities)) | 658 | if (SYN_CAP_PASS_THROUGH(priv->capabilities)) |
657 | synaptics_pt_create(psmouse); | 659 | synaptics_pt_create(psmouse); |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 2d2f9fb3aded..a4c6f3522723 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -173,6 +173,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
173 | DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), | 173 | DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), |
174 | }, | 174 | }, |
175 | }, | 175 | }, |
176 | { | ||
177 | .ident = "Sony Vaio FS-115b", | ||
178 | .matches = { | ||
179 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
180 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"), | ||
181 | }, | ||
182 | }, | ||
176 | { } | 183 | { } |
177 | }; | 184 | }; |
178 | 185 | ||
diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c index cf6a6f2248ac..314fc0830d90 100644 --- a/drivers/macintosh/macio-adb.c +++ b/drivers/macintosh/macio-adb.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <asm/irq.h> | 17 | #include <asm/irq.h> |
18 | #include <asm/system.h> | 18 | #include <asm/system.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/ioport.h> | ||
20 | 21 | ||
21 | struct preg { | 22 | struct preg { |
22 | unsigned char r; | 23 | unsigned char r; |
@@ -88,24 +89,26 @@ int macio_probe(void) | |||
88 | int macio_init(void) | 89 | int macio_init(void) |
89 | { | 90 | { |
90 | struct device_node *adbs; | 91 | struct device_node *adbs; |
92 | struct resource r; | ||
91 | 93 | ||
92 | adbs = find_compatible_devices("adb", "chrp,adb0"); | 94 | adbs = find_compatible_devices("adb", "chrp,adb0"); |
93 | if (adbs == 0) | 95 | if (adbs == 0) |
94 | return -ENXIO; | 96 | return -ENXIO; |
95 | 97 | ||
96 | #if 0 | 98 | #if 0 |
97 | { int i; | 99 | { int i = 0; |
98 | 100 | ||
99 | printk("macio_adb_init: node = %p, addrs =", adbs->node); | 101 | printk("macio_adb_init: node = %p, addrs =", adbs->node); |
100 | for (i = 0; i < adbs->n_addrs; ++i) | 102 | while(!of_address_to_resource(adbs, i, &r)) |
101 | printk(" %x(%x)", adbs->addrs[i].address, adbs->addrs[i].size); | 103 | printk(" %x(%x)", r.start, r.end - r.start); |
102 | printk(", intrs ="); | 104 | printk(", intrs ="); |
103 | for (i = 0; i < adbs->n_intrs; ++i) | 105 | for (i = 0; i < adbs->n_intrs; ++i) |
104 | printk(" %x", adbs->intrs[i].line); | 106 | printk(" %x", adbs->intrs[i].line); |
105 | printk("\n"); } | 107 | printk("\n"); } |
106 | #endif | 108 | #endif |
107 | 109 | if (of_address_to_resource(adbs, 0, &r)) | |
108 | adb = ioremap(adbs->addrs->address, sizeof(struct adb_regs)); | 110 | return -ENXIO; |
111 | adb = ioremap(r.start, sizeof(struct adb_regs)); | ||
109 | 112 | ||
110 | out_8(&adb->ctrl.r, 0); | 113 | out_8(&adb->ctrl.r, 0); |
111 | out_8(&adb->intr.r, 0); | 114 | out_8(&adb->intr.r, 0); |
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c index 92e6c5639dd3..015db40ad8a4 100644 --- a/drivers/sbus/char/aurora.c +++ b/drivers/sbus/char/aurora.c | |||
@@ -92,7 +92,6 @@ static struct Aurora_port aurora_port[AURORA_TNPORTS] = { | |||
92 | 92 | ||
93 | /* no longer used. static struct Aurora_board * IRQ_to_board[16] = { NULL, } ;*/ | 93 | /* no longer used. static struct Aurora_board * IRQ_to_board[16] = { NULL, } ;*/ |
94 | static unsigned char * tmp_buf = NULL; | 94 | static unsigned char * tmp_buf = NULL; |
95 | static DECLARE_MUTEX(tmp_buf_sem); | ||
96 | 95 | ||
97 | DECLARE_TASK_QUEUE(tq_aurora); | 96 | DECLARE_TASK_QUEUE(tq_aurora); |
98 | 97 | ||
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 4dd5c3f98167..8cbf0fc5a225 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c | |||
@@ -143,7 +143,6 @@ static int m68328_console_cbaud = DEFAULT_CBAUD; | |||
143 | * memory if large numbers of serial ports are open. | 143 | * memory if large numbers of serial ports are open. |
144 | */ | 144 | */ |
145 | static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */ | 145 | static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */ |
146 | DECLARE_MUTEX(tmp_buf_sem); | ||
147 | 146 | ||
148 | static inline int serial_paranoia_check(struct m68k_serial *info, | 147 | static inline int serial_paranoia_check(struct m68k_serial *info, |
149 | char *name, const char *routine) | 148 | char *name, const char *routine) |
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index 509dd0a04c54..5246b35301de 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig | |||
@@ -37,6 +37,16 @@ config USB_HIDINPUT | |||
37 | 37 | ||
38 | If unsure, say Y. | 38 | If unsure, say Y. |
39 | 39 | ||
40 | config USB_HIDINPUT_POWERBOOK | ||
41 | bool "Enable support for iBook/PowerBook special keys" | ||
42 | default n | ||
43 | depends on USB_HIDINPUT | ||
44 | help | ||
45 | Say Y here if you want support for the special keys (Fn, Numlock) on | ||
46 | Apple iBooks and PowerBooks. | ||
47 | |||
48 | If unsure, say N. | ||
49 | |||
40 | config HID_FF | 50 | config HID_FF |
41 | bool "Force feedback support (EXPERIMENTAL)" | 51 | bool "Force feedback support (EXPERIMENTAL)" |
42 | depends on USB_HIDINPUT && EXPERIMENTAL | 52 | depends on USB_HIDINPUT && EXPERIMENTAL |
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 5f52979af1c7..a91e72c41415 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
@@ -1450,6 +1450,9 @@ void hid_init_reports(struct hid_device *hid) | |||
1450 | #define USB_VENDOR_ID_APPLE 0x05ac | 1450 | #define USB_VENDOR_ID_APPLE 0x05ac |
1451 | #define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 | 1451 | #define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 |
1452 | 1452 | ||
1453 | #define USB_VENDOR_ID_CHERRY 0x046a | ||
1454 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 | ||
1455 | |||
1453 | /* | 1456 | /* |
1454 | * Alphabetically sorted blacklist by quirk type. | 1457 | * Alphabetically sorted blacklist by quirk type. |
1455 | */ | 1458 | */ |
@@ -1580,6 +1583,16 @@ static const struct hid_blacklist { | |||
1580 | { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, | 1583 | { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, |
1581 | { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, | 1584 | { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, |
1582 | 1585 | ||
1586 | { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION }, | ||
1587 | |||
1588 | { USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1589 | { USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1590 | { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1591 | { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1592 | { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1593 | { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1594 | { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1595 | |||
1583 | { 0, 0 } | 1596 | { 0, 0 } |
1584 | }; | 1597 | }; |
1585 | 1598 | ||
@@ -1626,6 +1639,20 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) | |||
1626 | usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma); | 1639 | usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma); |
1627 | } | 1640 | } |
1628 | 1641 | ||
1642 | /* | ||
1643 | * Cherry Cymotion keyboard have an invalid HID report descriptor, | ||
1644 | * that needs fixing before we can parse it. | ||
1645 | */ | ||
1646 | |||
1647 | static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize) | ||
1648 | { | ||
1649 | if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { | ||
1650 | info("Fixing up Cherry Cymotion report descriptor"); | ||
1651 | rdesc[11] = rdesc[16] = 0xff; | ||
1652 | rdesc[12] = rdesc[17] = 0x03; | ||
1653 | } | ||
1654 | } | ||
1655 | |||
1629 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) | 1656 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) |
1630 | { | 1657 | { |
1631 | struct usb_host_interface *interface = intf->cur_altsetting; | 1658 | struct usb_host_interface *interface = intf->cur_altsetting; |
@@ -1673,6 +1700,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
1673 | return NULL; | 1700 | return NULL; |
1674 | } | 1701 | } |
1675 | 1702 | ||
1703 | if ((quirks & HID_QUIRK_CYMOTION)) | ||
1704 | hid_fixup_cymotion_descriptor(rdesc, rsize); | ||
1705 | |||
1676 | #ifdef DEBUG_DATA | 1706 | #ifdef DEBUG_DATA |
1677 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); | 1707 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); |
1678 | for (n = 0; n < rsize; n++) | 1708 | for (n = 0; n < rsize; n++) |
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 192a03b28971..cb0d80f49252 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c | |||
@@ -73,6 +73,160 @@ static const struct { | |||
73 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) | 73 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) |
74 | #define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0) | 74 | #define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0) |
75 | 75 | ||
76 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK | ||
77 | |||
78 | struct hidinput_key_translation { | ||
79 | u16 from; | ||
80 | u16 to; | ||
81 | u8 flags; | ||
82 | }; | ||
83 | |||
84 | #define POWERBOOK_FLAG_FKEY 0x01 | ||
85 | |||
86 | static struct hidinput_key_translation powerbook_fn_keys[] = { | ||
87 | { KEY_BACKSPACE, KEY_DELETE }, | ||
88 | { KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY }, | ||
89 | { KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY }, | ||
90 | { KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY }, | ||
91 | { KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY }, | ||
92 | { KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY }, | ||
93 | { KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY }, | ||
94 | { KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY }, | ||
95 | { KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY }, | ||
96 | { KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY }, | ||
97 | { KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY }, | ||
98 | { KEY_UP, KEY_PAGEUP }, | ||
99 | { KEY_DOWN, KEY_PAGEDOWN }, | ||
100 | { KEY_LEFT, KEY_HOME }, | ||
101 | { KEY_RIGHT, KEY_END }, | ||
102 | { } | ||
103 | }; | ||
104 | |||
105 | static struct hidinput_key_translation powerbook_numlock_keys[] = { | ||
106 | { KEY_J, KEY_KP1 }, | ||
107 | { KEY_K, KEY_KP2 }, | ||
108 | { KEY_L, KEY_KP3 }, | ||
109 | { KEY_U, KEY_KP4 }, | ||
110 | { KEY_I, KEY_KP5 }, | ||
111 | { KEY_O, KEY_KP6 }, | ||
112 | { KEY_7, KEY_KP7 }, | ||
113 | { KEY_8, KEY_KP8 }, | ||
114 | { KEY_9, KEY_KP9 }, | ||
115 | { KEY_M, KEY_KP0 }, | ||
116 | { KEY_DOT, KEY_KPDOT }, | ||
117 | { KEY_SLASH, KEY_KPPLUS }, | ||
118 | { KEY_SEMICOLON, KEY_KPMINUS }, | ||
119 | { KEY_P, KEY_KPASTERISK }, | ||
120 | { KEY_MINUS, KEY_KPEQUAL }, | ||
121 | { KEY_0, KEY_KPSLASH }, | ||
122 | { KEY_F6, KEY_NUMLOCK }, | ||
123 | { KEY_KPENTER, KEY_KPENTER }, | ||
124 | { KEY_BACKSPACE, KEY_BACKSPACE }, | ||
125 | { } | ||
126 | }; | ||
127 | |||
128 | static int usbhid_pb_fnmode = 1; | ||
129 | module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644); | ||
130 | MODULE_PARM_DESC(pb_fnmode, | ||
131 | "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)"); | ||
132 | |||
133 | static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from) | ||
134 | { | ||
135 | struct hidinput_key_translation *trans; | ||
136 | |||
137 | /* Look for the translation */ | ||
138 | for (trans = table; trans->from; trans++) | ||
139 | if (trans->from == from) | ||
140 | return trans; | ||
141 | |||
142 | return NULL; | ||
143 | } | ||
144 | |||
145 | static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, | ||
146 | struct hid_usage *usage, __s32 value) | ||
147 | { | ||
148 | struct hidinput_key_translation *trans; | ||
149 | |||
150 | if (usage->code == KEY_FN) { | ||
151 | if (value) hid->quirks |= HID_QUIRK_POWERBOOK_FN_ON; | ||
152 | else hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON; | ||
153 | |||
154 | input_event(input, usage->type, usage->code, value); | ||
155 | |||
156 | return 1; | ||
157 | } | ||
158 | |||
159 | if (usbhid_pb_fnmode) { | ||
160 | int do_translate; | ||
161 | |||
162 | trans = find_translation(powerbook_fn_keys, usage->code); | ||
163 | if (trans) { | ||
164 | if (test_bit(usage->code, hid->pb_pressed_fn)) | ||
165 | do_translate = 1; | ||
166 | else if (trans->flags & POWERBOOK_FLAG_FKEY) | ||
167 | do_translate = | ||
168 | (usbhid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) || | ||
169 | (usbhid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)); | ||
170 | else | ||
171 | do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON); | ||
172 | |||
173 | if (do_translate) { | ||
174 | if (value) | ||
175 | set_bit(usage->code, hid->pb_pressed_fn); | ||
176 | else | ||
177 | clear_bit(usage->code, hid->pb_pressed_fn); | ||
178 | |||
179 | input_event(input, usage->type, trans->to, value); | ||
180 | |||
181 | return 1; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | if (test_bit(usage->code, hid->pb_pressed_numlock) || | ||
186 | test_bit(LED_NUML, input->led)) { | ||
187 | trans = find_translation(powerbook_numlock_keys, usage->code); | ||
188 | |||
189 | if (trans) { | ||
190 | if (value) | ||
191 | set_bit(usage->code, hid->pb_pressed_numlock); | ||
192 | else | ||
193 | clear_bit(usage->code, hid->pb_pressed_numlock); | ||
194 | |||
195 | input_event(input, usage->type, trans->to, value); | ||
196 | } | ||
197 | |||
198 | return 1; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static void hidinput_pb_setup(struct input_dev *input) | ||
206 | { | ||
207 | struct hidinput_key_translation *trans; | ||
208 | |||
209 | set_bit(KEY_NUMLOCK, input->keybit); | ||
210 | |||
211 | /* Enable all needed keys */ | ||
212 | for (trans = powerbook_fn_keys; trans->from; trans++) | ||
213 | set_bit(trans->to, input->keybit); | ||
214 | |||
215 | for (trans = powerbook_numlock_keys; trans->from; trans++) | ||
216 | set_bit(trans->to, input->keybit); | ||
217 | } | ||
218 | #else | ||
219 | static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, | ||
220 | struct hid_usage *usage, __s32 value) | ||
221 | { | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static inline void hidinput_pb_setup(struct input_dev *input) | ||
226 | { | ||
227 | } | ||
228 | #endif | ||
229 | |||
76 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, | 230 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, |
77 | struct hid_usage *usage) | 231 | struct hid_usage *usage) |
78 | { | 232 | { |
@@ -135,8 +289,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
135 | case HID_UP_SIMULATION: | 289 | case HID_UP_SIMULATION: |
136 | 290 | ||
137 | switch (usage->hid & 0xffff) { | 291 | switch (usage->hid & 0xffff) { |
138 | case 0xba: map_abs(ABS_RUDDER); break; | 292 | case 0xba: map_abs(ABS_RUDDER); break; |
139 | case 0xbb: map_abs(ABS_THROTTLE); break; | 293 | case 0xbb: map_abs(ABS_THROTTLE); break; |
294 | case 0xc4: map_abs(ABS_GAS); break; | ||
295 | case 0xc5: map_abs(ABS_BRAKE); break; | ||
296 | case 0xc8: map_abs(ABS_WHEEL); break; | ||
140 | default: goto ignore; | 297 | default: goto ignore; |
141 | } | 298 | } |
142 | break; | 299 | break; |
@@ -289,11 +446,19 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
289 | case 0x226: map_key_clear(KEY_STOP); break; | 446 | case 0x226: map_key_clear(KEY_STOP); break; |
290 | case 0x227: map_key_clear(KEY_REFRESH); break; | 447 | case 0x227: map_key_clear(KEY_REFRESH); break; |
291 | case 0x22a: map_key_clear(KEY_BOOKMARKS); break; | 448 | case 0x22a: map_key_clear(KEY_BOOKMARKS); break; |
449 | case 0x233: map_key_clear(KEY_SCROLLUP); break; | ||
450 | case 0x234: map_key_clear(KEY_SCROLLDOWN); break; | ||
292 | case 0x238: map_rel(REL_HWHEEL); break; | 451 | case 0x238: map_rel(REL_HWHEEL); break; |
293 | case 0x279: map_key_clear(KEY_REDO); break; | 452 | case 0x279: map_key_clear(KEY_REDO); break; |
294 | case 0x289: map_key_clear(KEY_REPLY); break; | 453 | case 0x289: map_key_clear(KEY_REPLY); break; |
295 | case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; | 454 | case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; |
296 | case 0x28c: map_key_clear(KEY_SEND); break; | 455 | case 0x28c: map_key_clear(KEY_SEND); break; |
456 | |||
457 | /* Reported on a Cherry Cymotion keyboard */ | ||
458 | case 0x301: map_key_clear(KEY_PROG1); break; | ||
459 | case 0x302: map_key_clear(KEY_PROG2); break; | ||
460 | case 0x303: map_key_clear(KEY_PROG3); break; | ||
461 | |||
297 | default: goto ignore; | 462 | default: goto ignore; |
298 | } | 463 | } |
299 | break; | 464 | break; |
@@ -325,7 +490,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
325 | 490 | ||
326 | set_bit(EV_REP, input->evbit); | 491 | set_bit(EV_REP, input->evbit); |
327 | switch(usage->hid & HID_USAGE) { | 492 | switch(usage->hid & HID_USAGE) { |
328 | case 0x003: map_key_clear(KEY_FN); break; | 493 | case 0x003: |
494 | /* The fn key on Apple PowerBooks */ | ||
495 | map_key_clear(KEY_FN); | ||
496 | hidinput_pb_setup(input); | ||
497 | break; | ||
498 | |||
329 | default: goto ignore; | 499 | default: goto ignore; |
330 | } | 500 | } |
331 | break; | 501 | break; |
@@ -482,6 +652,9 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
482 | return; | 652 | return; |
483 | } | 653 | } |
484 | 654 | ||
655 | if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value)) | ||
656 | return; | ||
657 | |||
485 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { | 658 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { |
486 | int hat_dir = usage->hat_dir; | 659 | int hat_dir = usage->hat_dir; |
487 | if (!hat_dir) | 660 | if (!hat_dir) |
@@ -524,7 +697,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
524 | return; | 697 | return; |
525 | } | 698 | } |
526 | 699 | ||
527 | if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ | 700 | if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ |
528 | return; | 701 | return; |
529 | 702 | ||
530 | input_event(input, usage->type, usage->code, value); | 703 | input_event(input, usage->type, usage->code, value); |
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index ee48a2276104..8b0d4346ce9c 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h | |||
@@ -235,17 +235,20 @@ struct hid_item { | |||
235 | * HID device quirks. | 235 | * HID device quirks. |
236 | */ | 236 | */ |
237 | 237 | ||
238 | #define HID_QUIRK_INVERT 0x001 | 238 | #define HID_QUIRK_INVERT 0x00000001 |
239 | #define HID_QUIRK_NOTOUCH 0x002 | 239 | #define HID_QUIRK_NOTOUCH 0x00000002 |
240 | #define HID_QUIRK_IGNORE 0x004 | 240 | #define HID_QUIRK_IGNORE 0x00000004 |
241 | #define HID_QUIRK_NOGET 0x008 | 241 | #define HID_QUIRK_NOGET 0x00000008 |
242 | #define HID_QUIRK_HIDDEV 0x010 | 242 | #define HID_QUIRK_HIDDEV 0x00000010 |
243 | #define HID_QUIRK_BADPAD 0x020 | 243 | #define HID_QUIRK_BADPAD 0x00000020 |
244 | #define HID_QUIRK_MULTI_INPUT 0x040 | 244 | #define HID_QUIRK_MULTI_INPUT 0x00000040 |
245 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x080 | 245 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080 |
246 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100 | 246 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100 |
247 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200 | 247 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200 |
248 | #define HID_QUIRK_2WHEEL_POWERMOUSE 0x400 | 248 | #define HID_QUIRK_2WHEEL_POWERMOUSE 0x00000400 |
249 | #define HID_QUIRK_CYMOTION 0x00000800 | ||
250 | #define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000 | ||
251 | #define HID_QUIRK_POWERBOOK_FN_ON 0x00002000 | ||
249 | 252 | ||
250 | /* | 253 | /* |
251 | * This is the global environment of the parser. This information is | 254 | * This is the global environment of the parser. This information is |
@@ -431,6 +434,11 @@ struct hid_device { /* device report descriptor */ | |||
431 | void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */ | 434 | void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */ |
432 | int (*ff_event)(struct hid_device *hid, struct input_dev *input, | 435 | int (*ff_event)(struct hid_device *hid, struct input_dev *input, |
433 | unsigned int type, unsigned int code, int value); | 436 | unsigned int type, unsigned int code, int value); |
437 | |||
438 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK | ||
439 | unsigned long pb_pressed_fn[NBITS(KEY_MAX)]; | ||
440 | unsigned long pb_pressed_numlock[NBITS(KEY_MAX)]; | ||
441 | #endif | ||
434 | }; | 442 | }; |
435 | 443 | ||
436 | #define HID_GLOBAL_STACK_SIZE 4 | 444 | #define HID_GLOBAL_STACK_SIZE 4 |
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c index 19e015d171aa..d9d9f656b8c9 100644 --- a/drivers/usb/input/pid.c +++ b/drivers/usb/input/pid.c | |||
@@ -259,7 +259,7 @@ static int hid_pid_upload_effect(struct input_dev *dev, | |||
259 | int hid_pid_init(struct hid_device *hid) | 259 | int hid_pid_init(struct hid_device *hid) |
260 | { | 260 | { |
261 | struct hid_ff_pid *private; | 261 | struct hid_ff_pid *private; |
262 | struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list); | 262 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); |
263 | struct input_dev *input_dev = hidinput->input; | 263 | struct input_dev *input_dev = hidinput->input; |
264 | 264 | ||
265 | private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); | 265 | private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); |
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index 48df4cfd5a42..d3e15df9e815 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c | |||
@@ -95,7 +95,7 @@ MODULE_LICENSE(DRIVER_LICENSE); | |||
95 | enum { | 95 | enum { |
96 | PENPARTNER = 0, | 96 | PENPARTNER = 0, |
97 | GRAPHIRE, | 97 | GRAPHIRE, |
98 | G4, | 98 | WACOM_G4, |
99 | PL, | 99 | PL, |
100 | INTUOS, | 100 | INTUOS, |
101 | INTUOS3, | 101 | INTUOS3, |
@@ -373,7 +373,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
373 | 373 | ||
374 | case 2: /* Mouse with wheel */ | 374 | case 2: /* Mouse with wheel */ |
375 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); | 375 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); |
376 | if (wacom->features->type == G4) { | 376 | if (wacom->features->type == WACOM_G4) { |
377 | rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03); | 377 | rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03); |
378 | input_report_rel(dev, REL_WHEEL, rw); | 378 | input_report_rel(dev, REL_WHEEL, rw); |
379 | } else | 379 | } else |
@@ -385,7 +385,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
385 | id = CURSOR_DEVICE_ID; | 385 | id = CURSOR_DEVICE_ID; |
386 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); | 386 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); |
387 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); | 387 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); |
388 | if (wacom->features->type == G4) | 388 | if (wacom->features->type == WACOM_G4) |
389 | input_report_abs(dev, ABS_DISTANCE, data[6]); | 389 | input_report_abs(dev, ABS_DISTANCE, data[6]); |
390 | else | 390 | else |
391 | input_report_abs(dev, ABS_DISTANCE, data[7]); | 391 | input_report_abs(dev, ABS_DISTANCE, data[7]); |
@@ -410,7 +410,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
410 | input_sync(dev); | 410 | input_sync(dev); |
411 | 411 | ||
412 | /* send pad data */ | 412 | /* send pad data */ |
413 | if (wacom->features->type == G4) { | 413 | if (wacom->features->type == WACOM_G4) { |
414 | /* fist time sending pad data */ | 414 | /* fist time sending pad data */ |
415 | if (wacom->tool[1] != BTN_TOOL_FINGER) { | 415 | if (wacom->tool[1] != BTN_TOOL_FINGER) { |
416 | wacom->id[1] = 0; | 416 | wacom->id[1] = 0; |
@@ -713,8 +713,8 @@ static struct wacom_features wacom_features[] = { | |||
713 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 713 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
714 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 714 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
715 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 715 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
716 | { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, G4, wacom_graphire_irq }, | 716 | { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, WACOM_G4, wacom_graphire_irq }, |
717 | { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, G4, wacom_graphire_irq }, | 717 | { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, WACOM_G4, wacom_graphire_irq }, |
718 | { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 718 | { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
719 | { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, | 719 | { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, |
720 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 720 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
@@ -859,7 +859,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
859 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); | 859 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); |
860 | 860 | ||
861 | switch (wacom->features->type) { | 861 | switch (wacom->features->type) { |
862 | case G4: | 862 | case WACOM_G4: |
863 | input_dev->evbit[0] |= BIT(EV_MSC); | 863 | input_dev->evbit[0] |= BIT(EV_MSC); |
864 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); | 864 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); |
865 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | 865 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 9ffff1938239..0eb883f44ada 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -43,8 +43,6 @@ static int debug; | |||
43 | #define PL2303_BUF_SIZE 1024 | 43 | #define PL2303_BUF_SIZE 1024 |
44 | #define PL2303_TMP_BUF_SIZE 1024 | 44 | #define PL2303_TMP_BUF_SIZE 1024 |
45 | 45 | ||
46 | static DECLARE_MUTEX(pl2303_tmp_buf_sem); | ||
47 | |||
48 | struct pl2303_buf { | 46 | struct pl2303_buf { |
49 | unsigned int buf_size; | 47 | unsigned int buf_size; |
50 | char *buf_buf; | 48 | char *buf_buf; |
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index fb117b74809e..9bdd077d6f55 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c | |||
@@ -81,6 +81,30 @@ void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop | |||
81 | __proc_device_tree_add_prop(pde, prop); | 81 | __proc_device_tree_add_prop(pde, prop); |
82 | } | 82 | } |
83 | 83 | ||
84 | void proc_device_tree_remove_prop(struct proc_dir_entry *pde, | ||
85 | struct property *prop) | ||
86 | { | ||
87 | remove_proc_entry(prop->name, pde); | ||
88 | } | ||
89 | |||
90 | void proc_device_tree_update_prop(struct proc_dir_entry *pde, | ||
91 | struct property *newprop, | ||
92 | struct property *oldprop) | ||
93 | { | ||
94 | struct proc_dir_entry *ent; | ||
95 | |||
96 | for (ent = pde->subdir; ent != NULL; ent = ent->next) | ||
97 | if (ent->data == oldprop) | ||
98 | break; | ||
99 | if (ent == NULL) { | ||
100 | printk(KERN_WARNING "device-tree: property \"%s\" " | ||
101 | " does not exist\n", oldprop->name); | ||
102 | } else { | ||
103 | ent->data = newprop; | ||
104 | ent->size = newprop->length; | ||
105 | } | ||
106 | } | ||
107 | |||
84 | /* | 108 | /* |
85 | * Process a node, adding entries for its children and its properties. | 109 | * Process a node, adding entries for its children and its properties. |
86 | */ | 110 | */ |
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index a9f4421ddb6f..3ada9dcf55b8 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c | |||
@@ -49,7 +49,7 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count | |||
49 | 49 | ||
50 | sb = inode->i_sb; | 50 | sb = inode->i_sb; |
51 | uspi = UFS_SB(sb)->s_uspi; | 51 | uspi = UFS_SB(sb)->s_uspi; |
52 | usb1 = ubh_get_usb_first(USPI_UBH); | 52 | usb1 = ubh_get_usb_first(uspi); |
53 | 53 | ||
54 | UFSD(("ENTER, fragment %u, count %u\n", fragment, count)) | 54 | UFSD(("ENTER, fragment %u, count %u\n", fragment, count)) |
55 | 55 | ||
@@ -81,8 +81,9 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count | |||
81 | for (i = bit; i < end_bit; i++) { | 81 | for (i = bit; i < end_bit; i++) { |
82 | if (ubh_isclr (UCPI_UBH, ucpi->c_freeoff, i)) | 82 | if (ubh_isclr (UCPI_UBH, ucpi->c_freeoff, i)) |
83 | ubh_setbit (UCPI_UBH, ucpi->c_freeoff, i); | 83 | ubh_setbit (UCPI_UBH, ucpi->c_freeoff, i); |
84 | else ufs_error (sb, "ufs_free_fragments", | 84 | else |
85 | "bit already cleared for fragment %u", i); | 85 | ufs_error (sb, "ufs_free_fragments", |
86 | "bit already cleared for fragment %u", i); | ||
86 | } | 87 | } |
87 | 88 | ||
88 | DQUOT_FREE_BLOCK (inode, count); | 89 | DQUOT_FREE_BLOCK (inode, count); |
@@ -143,7 +144,7 @@ void ufs_free_blocks (struct inode * inode, unsigned fragment, unsigned count) { | |||
143 | 144 | ||
144 | sb = inode->i_sb; | 145 | sb = inode->i_sb; |
145 | uspi = UFS_SB(sb)->s_uspi; | 146 | uspi = UFS_SB(sb)->s_uspi; |
146 | usb1 = ubh_get_usb_first(USPI_UBH); | 147 | usb1 = ubh_get_usb_first(uspi); |
147 | 148 | ||
148 | UFSD(("ENTER, fragment %u, count %u\n", fragment, count)) | 149 | UFSD(("ENTER, fragment %u, count %u\n", fragment, count)) |
149 | 150 | ||
@@ -247,7 +248,7 @@ unsigned ufs_new_fragments (struct inode * inode, __fs32 * p, unsigned fragment, | |||
247 | 248 | ||
248 | sb = inode->i_sb; | 249 | sb = inode->i_sb; |
249 | uspi = UFS_SB(sb)->s_uspi; | 250 | uspi = UFS_SB(sb)->s_uspi; |
250 | usb1 = ubh_get_usb_first(USPI_UBH); | 251 | usb1 = ubh_get_usb_first(uspi); |
251 | *err = -ENOSPC; | 252 | *err = -ENOSPC; |
252 | 253 | ||
253 | lock_super (sb); | 254 | lock_super (sb); |
@@ -407,7 +408,7 @@ ufs_add_fragments (struct inode * inode, unsigned fragment, | |||
407 | 408 | ||
408 | sb = inode->i_sb; | 409 | sb = inode->i_sb; |
409 | uspi = UFS_SB(sb)->s_uspi; | 410 | uspi = UFS_SB(sb)->s_uspi; |
410 | usb1 = ubh_get_usb_first (USPI_UBH); | 411 | usb1 = ubh_get_usb_first (uspi); |
411 | count = newcount - oldcount; | 412 | count = newcount - oldcount; |
412 | 413 | ||
413 | cgno = ufs_dtog(fragment); | 414 | cgno = ufs_dtog(fragment); |
@@ -490,7 +491,7 @@ static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno, | |||
490 | 491 | ||
491 | sb = inode->i_sb; | 492 | sb = inode->i_sb; |
492 | uspi = UFS_SB(sb)->s_uspi; | 493 | uspi = UFS_SB(sb)->s_uspi; |
493 | usb1 = ubh_get_usb_first(USPI_UBH); | 494 | usb1 = ubh_get_usb_first(uspi); |
494 | oldcg = cgno; | 495 | oldcg = cgno; |
495 | 496 | ||
496 | /* | 497 | /* |
@@ -606,7 +607,7 @@ static unsigned ufs_alloccg_block (struct inode * inode, | |||
606 | 607 | ||
607 | sb = inode->i_sb; | 608 | sb = inode->i_sb; |
608 | uspi = UFS_SB(sb)->s_uspi; | 609 | uspi = UFS_SB(sb)->s_uspi; |
609 | usb1 = ubh_get_usb_first(USPI_UBH); | 610 | usb1 = ubh_get_usb_first(uspi); |
610 | ucg = ubh_get_ucg(UCPI_UBH); | 611 | ucg = ubh_get_ucg(UCPI_UBH); |
611 | 612 | ||
612 | if (goal == 0) { | 613 | if (goal == 0) { |
@@ -663,7 +664,7 @@ static unsigned ufs_bitmap_search (struct super_block * sb, | |||
663 | UFSD(("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count)) | 664 | UFSD(("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count)) |
664 | 665 | ||
665 | uspi = UFS_SB(sb)->s_uspi; | 666 | uspi = UFS_SB(sb)->s_uspi; |
666 | usb1 = ubh_get_usb_first (USPI_UBH); | 667 | usb1 = ubh_get_usb_first (uspi); |
667 | ucg = ubh_get_ucg(UCPI_UBH); | 668 | ucg = ubh_get_ucg(UCPI_UBH); |
668 | 669 | ||
669 | if (goal) | 670 | if (goal) |
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 0938945b9cbc..c7a47ed4f430 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c | |||
@@ -72,7 +72,7 @@ void ufs_free_inode (struct inode * inode) | |||
72 | 72 | ||
73 | sb = inode->i_sb; | 73 | sb = inode->i_sb; |
74 | uspi = UFS_SB(sb)->s_uspi; | 74 | uspi = UFS_SB(sb)->s_uspi; |
75 | usb1 = ubh_get_usb_first(USPI_UBH); | 75 | usb1 = ubh_get_usb_first(uspi); |
76 | 76 | ||
77 | ino = inode->i_ino; | 77 | ino = inode->i_ino; |
78 | 78 | ||
@@ -167,7 +167,7 @@ struct inode * ufs_new_inode(struct inode * dir, int mode) | |||
167 | ufsi = UFS_I(inode); | 167 | ufsi = UFS_I(inode); |
168 | sbi = UFS_SB(sb); | 168 | sbi = UFS_SB(sb); |
169 | uspi = sbi->s_uspi; | 169 | uspi = sbi->s_uspi; |
170 | usb1 = ubh_get_usb_first(USPI_UBH); | 170 | usb1 = ubh_get_usb_first(uspi); |
171 | 171 | ||
172 | lock_super (sb); | 172 | lock_super (sb); |
173 | 173 | ||
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 55f4aa16e3fc..e0c04e36a051 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c | |||
@@ -61,7 +61,7 @@ static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t off | |||
61 | int n = 0; | 61 | int n = 0; |
62 | 62 | ||
63 | 63 | ||
64 | UFSD(("ptrs=uspi->s_apb = %d,double_blocks=%d \n",ptrs,double_blocks)); | 64 | UFSD(("ptrs=uspi->s_apb = %d,double_blocks=%ld \n",ptrs,double_blocks)); |
65 | if (i_block < 0) { | 65 | if (i_block < 0) { |
66 | ufs_warning(inode->i_sb, "ufs_block_to_path", "block < 0"); | 66 | ufs_warning(inode->i_sb, "ufs_block_to_path", "block < 0"); |
67 | } else if (i_block < direct_blocks) { | 67 | } else if (i_block < direct_blocks) { |
@@ -104,7 +104,7 @@ u64 ufs_frag_map(struct inode *inode, sector_t frag) | |||
104 | unsigned flags = UFS_SB(sb)->s_flags; | 104 | unsigned flags = UFS_SB(sb)->s_flags; |
105 | u64 temp = 0L; | 105 | u64 temp = 0L; |
106 | 106 | ||
107 | UFSD((": frag = %lu depth = %d\n",frag,depth)); | 107 | UFSD((": frag = %llu depth = %d\n", (unsigned long long)frag, depth)); |
108 | UFSD((": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n",uspi->s_fpbshift,uspi->s_apbmask,mask)); | 108 | UFSD((": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n",uspi->s_fpbshift,uspi->s_apbmask,mask)); |
109 | 109 | ||
110 | if (depth == 0) | 110 | if (depth == 0) |
@@ -365,9 +365,10 @@ repeat: | |||
365 | sync_dirty_buffer(bh); | 365 | sync_dirty_buffer(bh); |
366 | inode->i_ctime = CURRENT_TIME_SEC; | 366 | inode->i_ctime = CURRENT_TIME_SEC; |
367 | mark_inode_dirty(inode); | 367 | mark_inode_dirty(inode); |
368 | UFSD(("result %u\n", tmp + blockoff)); | ||
368 | out: | 369 | out: |
369 | brelse (bh); | 370 | brelse (bh); |
370 | UFSD(("EXIT, result %u\n", tmp + blockoff)) | 371 | UFSD(("EXIT\n")); |
371 | return result; | 372 | return result; |
372 | } | 373 | } |
373 | 374 | ||
@@ -386,7 +387,7 @@ static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buf | |||
386 | 387 | ||
387 | if (!create) { | 388 | if (!create) { |
388 | phys64 = ufs_frag_map(inode, fragment); | 389 | phys64 = ufs_frag_map(inode, fragment); |
389 | UFSD(("phys64 = %lu \n",phys64)); | 390 | UFSD(("phys64 = %llu \n",phys64)); |
390 | if (phys64) | 391 | if (phys64) |
391 | map_bh(bh_result, sb, phys64); | 392 | map_bh(bh_result, sb, phys64); |
392 | return 0; | 393 | return 0; |
@@ -401,7 +402,7 @@ static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buf | |||
401 | 402 | ||
402 | lock_kernel(); | 403 | lock_kernel(); |
403 | 404 | ||
404 | UFSD(("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment)) | 405 | UFSD(("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment)) |
405 | if (fragment < 0) | 406 | if (fragment < 0) |
406 | goto abort_negative; | 407 | goto abort_negative; |
407 | if (fragment > | 408 | if (fragment > |
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index e9a42c711a9e..d4aacee593ff 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
@@ -221,7 +221,7 @@ void ufs_error (struct super_block * sb, const char * function, | |||
221 | va_list args; | 221 | va_list args; |
222 | 222 | ||
223 | uspi = UFS_SB(sb)->s_uspi; | 223 | uspi = UFS_SB(sb)->s_uspi; |
224 | usb1 = ubh_get_usb_first(USPI_UBH); | 224 | usb1 = ubh_get_usb_first(uspi); |
225 | 225 | ||
226 | if (!(sb->s_flags & MS_RDONLY)) { | 226 | if (!(sb->s_flags & MS_RDONLY)) { |
227 | usb1->fs_clean = UFS_FSBAD; | 227 | usb1->fs_clean = UFS_FSBAD; |
@@ -253,7 +253,7 @@ void ufs_panic (struct super_block * sb, const char * function, | |||
253 | va_list args; | 253 | va_list args; |
254 | 254 | ||
255 | uspi = UFS_SB(sb)->s_uspi; | 255 | uspi = UFS_SB(sb)->s_uspi; |
256 | usb1 = ubh_get_usb_first(USPI_UBH); | 256 | usb1 = ubh_get_usb_first(uspi); |
257 | 257 | ||
258 | if (!(sb->s_flags & MS_RDONLY)) { | 258 | if (!(sb->s_flags & MS_RDONLY)) { |
259 | usb1->fs_clean = UFS_FSBAD; | 259 | usb1->fs_clean = UFS_FSBAD; |
@@ -420,21 +420,18 @@ static int ufs_read_cylinder_structures (struct super_block *sb) { | |||
420 | if (i + uspi->s_fpb > blks) | 420 | if (i + uspi->s_fpb > blks) |
421 | size = (blks - i) * uspi->s_fsize; | 421 | size = (blks - i) * uspi->s_fsize; |
422 | 422 | ||
423 | if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { | 423 | if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) |
424 | ubh = ubh_bread(sb, | 424 | ubh = ubh_bread(sb, |
425 | fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_csaddr) + i, size); | 425 | fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_csaddr) + i, size); |
426 | if (!ubh) | 426 | else |
427 | goto failed; | ||
428 | ubh_ubhcpymem (space, ubh, size); | ||
429 | sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space; | ||
430 | } | ||
431 | else { | ||
432 | ubh = ubh_bread(sb, uspi->s_csaddr + i, size); | 427 | ubh = ubh_bread(sb, uspi->s_csaddr + i, size); |
433 | if (!ubh) | 428 | |
434 | goto failed; | 429 | if (!ubh) |
435 | ubh_ubhcpymem(space, ubh, size); | 430 | goto failed; |
436 | sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space; | 431 | |
437 | } | 432 | ubh_ubhcpymem (space, ubh, size); |
433 | sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space; | ||
434 | |||
438 | space += size; | 435 | space += size; |
439 | ubh_brelse (ubh); | 436 | ubh_brelse (ubh); |
440 | ubh = NULL; | 437 | ubh = NULL; |
@@ -539,6 +536,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
539 | struct inode *inode; | 536 | struct inode *inode; |
540 | unsigned block_size, super_block_size; | 537 | unsigned block_size, super_block_size; |
541 | unsigned flags; | 538 | unsigned flags; |
539 | unsigned super_block_offset; | ||
542 | 540 | ||
543 | uspi = NULL; | 541 | uspi = NULL; |
544 | ubh = NULL; | 542 | ubh = NULL; |
@@ -586,10 +584,11 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
586 | if (!uspi) | 584 | if (!uspi) |
587 | goto failed; | 585 | goto failed; |
588 | 586 | ||
587 | super_block_offset=UFS_SBLOCK; | ||
588 | |||
589 | /* Keep 2Gig file limit. Some UFS variants need to override | 589 | /* Keep 2Gig file limit. Some UFS variants need to override |
590 | this but as I don't know which I'll let those in the know loosen | 590 | this but as I don't know which I'll let those in the know loosen |
591 | the rules */ | 591 | the rules */ |
592 | |||
593 | switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) { | 592 | switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) { |
594 | case UFS_MOUNT_UFSTYPE_44BSD: | 593 | case UFS_MOUNT_UFSTYPE_44BSD: |
595 | UFSD(("ufstype=44bsd\n")) | 594 | UFSD(("ufstype=44bsd\n")) |
@@ -601,7 +600,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
601 | flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; | 600 | flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; |
602 | break; | 601 | break; |
603 | case UFS_MOUNT_UFSTYPE_UFS2: | 602 | case UFS_MOUNT_UFSTYPE_UFS2: |
604 | UFSD(("ufstype=ufs2\n")) | 603 | UFSD(("ufstype=ufs2\n")); |
604 | super_block_offset=SBLOCK_UFS2; | ||
605 | uspi->s_fsize = block_size = 512; | 605 | uspi->s_fsize = block_size = 512; |
606 | uspi->s_fmask = ~(512 - 1); | 606 | uspi->s_fmask = ~(512 - 1); |
607 | uspi->s_fshift = 9; | 607 | uspi->s_fshift = 9; |
@@ -725,19 +725,16 @@ again: | |||
725 | /* | 725 | /* |
726 | * read ufs super block from device | 726 | * read ufs super block from device |
727 | */ | 727 | */ |
728 | if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { | 728 | |
729 | ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + SBLOCK_UFS2/block_size, super_block_size); | 729 | ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + super_block_offset/block_size, super_block_size); |
730 | } | 730 | |
731 | else { | ||
732 | ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + UFS_SBLOCK/block_size, super_block_size); | ||
733 | } | ||
734 | if (!ubh) | 731 | if (!ubh) |
735 | goto failed; | 732 | goto failed; |
736 | 733 | ||
737 | 734 | ||
738 | usb1 = ubh_get_usb_first(USPI_UBH); | 735 | usb1 = ubh_get_usb_first(uspi); |
739 | usb2 = ubh_get_usb_second(USPI_UBH); | 736 | usb2 = ubh_get_usb_second(uspi); |
740 | usb3 = ubh_get_usb_third(USPI_UBH); | 737 | usb3 = ubh_get_usb_third(uspi); |
741 | usb = (struct ufs_super_block *) | 738 | usb = (struct ufs_super_block *) |
742 | ((struct ufs_buffer_head *)uspi)->bh[0]->b_data ; | 739 | ((struct ufs_buffer_head *)uspi)->bh[0]->b_data ; |
743 | 740 | ||
@@ -1006,8 +1003,8 @@ static void ufs_write_super (struct super_block *sb) { | |||
1006 | UFSD(("ENTER\n")) | 1003 | UFSD(("ENTER\n")) |
1007 | flags = UFS_SB(sb)->s_flags; | 1004 | flags = UFS_SB(sb)->s_flags; |
1008 | uspi = UFS_SB(sb)->s_uspi; | 1005 | uspi = UFS_SB(sb)->s_uspi; |
1009 | usb1 = ubh_get_usb_first(USPI_UBH); | 1006 | usb1 = ubh_get_usb_first(uspi); |
1010 | usb3 = ubh_get_usb_third(USPI_UBH); | 1007 | usb3 = ubh_get_usb_third(uspi); |
1011 | 1008 | ||
1012 | if (!(sb->s_flags & MS_RDONLY)) { | 1009 | if (!(sb->s_flags & MS_RDONLY)) { |
1013 | usb1->fs_time = cpu_to_fs32(sb, get_seconds()); | 1010 | usb1->fs_time = cpu_to_fs32(sb, get_seconds()); |
@@ -1049,8 +1046,8 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
1049 | 1046 | ||
1050 | uspi = UFS_SB(sb)->s_uspi; | 1047 | uspi = UFS_SB(sb)->s_uspi; |
1051 | flags = UFS_SB(sb)->s_flags; | 1048 | flags = UFS_SB(sb)->s_flags; |
1052 | usb1 = ubh_get_usb_first(USPI_UBH); | 1049 | usb1 = ubh_get_usb_first(uspi); |
1053 | usb3 = ubh_get_usb_third(USPI_UBH); | 1050 | usb3 = ubh_get_usb_third(uspi); |
1054 | 1051 | ||
1055 | /* | 1052 | /* |
1056 | * Allow the "check" option to be passed as a remount option. | 1053 | * Allow the "check" option to be passed as a remount option. |
@@ -1124,7 +1121,7 @@ static int ufs_statfs (struct super_block *sb, struct kstatfs *buf) | |||
1124 | lock_kernel(); | 1121 | lock_kernel(); |
1125 | 1122 | ||
1126 | uspi = UFS_SB(sb)->s_uspi; | 1123 | uspi = UFS_SB(sb)->s_uspi; |
1127 | usb1 = ubh_get_usb_first (USPI_UBH); | 1124 | usb1 = ubh_get_usb_first (uspi); |
1128 | usb = (struct ufs_super_block *) | 1125 | usb = (struct ufs_super_block *) |
1129 | ((struct ufs_buffer_head *)uspi)->bh[0]->b_data ; | 1126 | ((struct ufs_buffer_head *)uspi)->bh[0]->b_data ; |
1130 | 1127 | ||
diff --git a/fs/ufs/util.h b/fs/ufs/util.h index e45ad5379872..48d6d9bcc157 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h | |||
@@ -249,18 +249,28 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head | |||
249 | 249 | ||
250 | 250 | ||
251 | /* | 251 | /* |
252 | * macros to get important structures from ufs_buffer_head | 252 | * macros and inline function to get important structures from ufs_sb_private_info |
253 | */ | 253 | */ |
254 | #define ubh_get_usb_first(ubh) \ | ||
255 | ((struct ufs_super_block_first *)((ubh)->bh[0]->b_data)) | ||
256 | 254 | ||
257 | #define ubh_get_usb_second(ubh) \ | 255 | static inline void *get_usb_offset(struct ufs_sb_private_info *uspi, |
258 | ((struct ufs_super_block_second *)((ubh)->\ | 256 | unsigned int offset) |
259 | bh[UFS_SECTOR_SIZE >> uspi->s_fshift]->b_data + (UFS_SECTOR_SIZE & ~uspi->s_fmask))) | 257 | { |
258 | unsigned int index; | ||
259 | |||
260 | index = offset >> uspi->s_fshift; | ||
261 | offset &= ~uspi->s_fmask; | ||
262 | return uspi->s_ubh.bh[index]->b_data + offset; | ||
263 | } | ||
264 | |||
265 | #define ubh_get_usb_first(uspi) \ | ||
266 | ((struct ufs_super_block_first *)get_usb_offset((uspi), 0)) | ||
267 | |||
268 | #define ubh_get_usb_second(uspi) \ | ||
269 | ((struct ufs_super_block_second *)get_usb_offset((uspi), UFS_SECTOR_SIZE)) | ||
270 | |||
271 | #define ubh_get_usb_third(uspi) \ | ||
272 | ((struct ufs_super_block_third *)get_usb_offset((uspi), 2*UFS_SECTOR_SIZE)) | ||
260 | 273 | ||
261 | #define ubh_get_usb_third(ubh) \ | ||
262 | ((struct ufs_super_block_third *)((ubh)-> \ | ||
263 | bh[UFS_SECTOR_SIZE*2 >> uspi->s_fshift]->b_data + (UFS_SECTOR_SIZE*2 & ~uspi->s_fmask))) | ||
264 | 274 | ||
265 | #define ubh_get_ucg(ubh) \ | 275 | #define ubh_get_ucg(ubh) \ |
266 | ((struct ufs_cylinder_group *)((ubh)->bh[0]->b_data)) | 276 | ((struct ufs_cylinder_group *)((ubh)->bh[0]->b_data)) |
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h index a74b68104559..8c0fc227f0fb 100644 --- a/include/asm-ia64/kprobes.h +++ b/include/asm-ia64/kprobes.h | |||
@@ -68,10 +68,14 @@ struct prev_kprobe { | |||
68 | unsigned long status; | 68 | unsigned long status; |
69 | }; | 69 | }; |
70 | 70 | ||
71 | #define MAX_PARAM_RSE_SIZE (0x60+0x60/0x3f) | ||
71 | /* per-cpu kprobe control block */ | 72 | /* per-cpu kprobe control block */ |
72 | struct kprobe_ctlblk { | 73 | struct kprobe_ctlblk { |
73 | unsigned long kprobe_status; | 74 | unsigned long kprobe_status; |
74 | struct pt_regs jprobe_saved_regs; | 75 | struct pt_regs jprobe_saved_regs; |
76 | unsigned long jprobes_saved_stacked_regs[MAX_PARAM_RSE_SIZE]; | ||
77 | unsigned long *bsp; | ||
78 | unsigned long cfm; | ||
75 | struct prev_kprobe prev_kprobe; | 79 | struct prev_kprobe prev_kprobe; |
76 | }; | 80 | }; |
77 | 81 | ||
@@ -118,5 +122,7 @@ extern int kprobe_exceptions_notify(struct notifier_block *self, | |||
118 | static inline void jprobe_return(void) | 122 | static inline void jprobe_return(void) |
119 | { | 123 | { |
120 | } | 124 | } |
125 | extern void invalidate_stacked_regs(void); | ||
126 | extern void flush_register_stack(void); | ||
121 | 127 | ||
122 | #endif /* _ASM_KPROBES_H */ | 128 | #endif /* _ASM_KPROBES_H */ |
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 2a8b0d92a5d6..8b9e10e7cdba 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h | |||
@@ -75,7 +75,8 @@ | |||
75 | #define SN_SAL_IOIF_GET_HUBDEV_INFO 0x02000055 | 75 | #define SN_SAL_IOIF_GET_HUBDEV_INFO 0x02000055 |
76 | #define SN_SAL_IOIF_GET_PCIBUS_INFO 0x02000056 | 76 | #define SN_SAL_IOIF_GET_PCIBUS_INFO 0x02000056 |
77 | #define SN_SAL_IOIF_GET_PCIDEV_INFO 0x02000057 | 77 | #define SN_SAL_IOIF_GET_PCIDEV_INFO 0x02000057 |
78 | #define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058 | 78 | #define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058 // deprecated |
79 | #define SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST 0x0200005a | ||
79 | 80 | ||
80 | #define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060 | 81 | #define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060 |
81 | #define SN_SAL_BTE_RECOVER 0x02000061 | 82 | #define SN_SAL_BTE_RECOVER 0x02000061 |
@@ -1100,7 +1101,7 @@ ia64_sn_bte_recovery(nasid_t nasid) | |||
1100 | struct ia64_sal_retval rv; | 1101 | struct ia64_sal_retval rv; |
1101 | 1102 | ||
1102 | rv.status = 0; | 1103 | rv.status = 0; |
1103 | SAL_CALL_NOLOCK(rv, SN_SAL_BTE_RECOVER, 0, 0, 0, 0, 0, 0, 0); | 1104 | SAL_CALL_NOLOCK(rv, SN_SAL_BTE_RECOVER, (u64)nasid, 0, 0, 0, 0, 0, 0); |
1104 | if (rv.status == SALRET_NOT_IMPLEMENTED) | 1105 | if (rv.status == SALRET_NOT_IMPLEMENTED) |
1105 | return 0; | 1106 | return 0; |
1106 | return (int) rv.status; | 1107 | return (int) rv.status; |
diff --git a/include/asm-ia64/sn/xp.h b/include/asm-ia64/sn/xp.h index 49faf8f26430..203945ae034e 100644 --- a/include/asm-ia64/sn/xp.h +++ b/include/asm-ia64/sn/xp.h | |||
@@ -227,7 +227,9 @@ enum xpc_retval { | |||
227 | 227 | ||
228 | xpcOpenCloseError, /* 50: channel open/close protocol error */ | 228 | xpcOpenCloseError, /* 50: channel open/close protocol error */ |
229 | 229 | ||
230 | xpcUnknownReason /* 51: unknown reason -- must be last in list */ | 230 | xpcDisconnected, /* 51: channel disconnected (closed) */ |
231 | |||
232 | xpcUnknownReason /* 52: unknown reason -- must be last in list */ | ||
231 | }; | 233 | }; |
232 | 234 | ||
233 | 235 | ||
diff --git a/arch/ia64/sn/kernel/xpc.h b/include/asm-ia64/sn/xpc.h index 5483a9f227d4..87e9cd588510 100644 --- a/arch/ia64/sn/kernel/xpc.h +++ b/include/asm-ia64/sn/xpc.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. | 6 | * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | 9 | ||
@@ -11,8 +11,8 @@ | |||
11 | * Cross Partition Communication (XPC) structures and macros. | 11 | * Cross Partition Communication (XPC) structures and macros. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #ifndef _IA64_SN_KERNEL_XPC_H | 14 | #ifndef _ASM_IA64_SN_XPC_H |
15 | #define _IA64_SN_KERNEL_XPC_H | 15 | #define _ASM_IA64_SN_XPC_H |
16 | 16 | ||
17 | 17 | ||
18 | #include <linux/config.h> | 18 | #include <linux/config.h> |
@@ -663,6 +663,7 @@ extern struct xpc_registration xpc_registrations[]; | |||
663 | extern struct device *xpc_part; | 663 | extern struct device *xpc_part; |
664 | extern struct device *xpc_chan; | 664 | extern struct device *xpc_chan; |
665 | extern int xpc_disengage_request_timelimit; | 665 | extern int xpc_disengage_request_timelimit; |
666 | extern int xpc_disengage_request_timedout; | ||
666 | extern irqreturn_t xpc_notify_IRQ_handler(int, void *, struct pt_regs *); | 667 | extern irqreturn_t xpc_notify_IRQ_handler(int, void *, struct pt_regs *); |
667 | extern void xpc_dropped_IPI_check(struct xpc_partition *); | 668 | extern void xpc_dropped_IPI_check(struct xpc_partition *); |
668 | extern void xpc_activate_partition(struct xpc_partition *); | 669 | extern void xpc_activate_partition(struct xpc_partition *); |
@@ -707,7 +708,7 @@ extern void xpc_connected_callout(struct xpc_channel *); | |||
707 | extern void xpc_deliver_msg(struct xpc_channel *); | 708 | extern void xpc_deliver_msg(struct xpc_channel *); |
708 | extern void xpc_disconnect_channel(const int, struct xpc_channel *, | 709 | extern void xpc_disconnect_channel(const int, struct xpc_channel *, |
709 | enum xpc_retval, unsigned long *); | 710 | enum xpc_retval, unsigned long *); |
710 | extern void xpc_disconnecting_callout(struct xpc_channel *); | 711 | extern void xpc_disconnect_callout(struct xpc_channel *, enum xpc_retval); |
711 | extern void xpc_partition_going_down(struct xpc_partition *, enum xpc_retval); | 712 | extern void xpc_partition_going_down(struct xpc_partition *, enum xpc_retval); |
712 | extern void xpc_teardown_infrastructure(struct xpc_partition *); | 713 | extern void xpc_teardown_infrastructure(struct xpc_partition *); |
713 | 714 | ||
@@ -1269,5 +1270,5 @@ xpc_check_for_channel_activity(struct xpc_partition *part) | |||
1269 | } | 1270 | } |
1270 | 1271 | ||
1271 | 1272 | ||
1272 | #endif /* _IA64_SN_KERNEL_XPC_H */ | 1273 | #endif /* _ASM_IA64_SN_XPC_H */ |
1273 | 1274 | ||
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h index 653bb7f9a753..1d6518fe1f02 100644 --- a/include/asm-ia64/thread_info.h +++ b/include/asm-ia64/thread_info.h | |||
@@ -93,6 +93,7 @@ struct thread_info { | |||
93 | #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ | 93 | #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ |
94 | #define TIF_MEMDIE 17 | 94 | #define TIF_MEMDIE 17 |
95 | #define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */ | 95 | #define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */ |
96 | #define TIF_DB_DISABLED 19 /* debug trap disabled for fsyscall */ | ||
96 | 97 | ||
97 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) | 98 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) |
98 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) | 99 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) |
@@ -100,9 +101,10 @@ struct thread_info { | |||
100 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) | 101 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) |
101 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) | 102 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) |
102 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) | 103 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) |
103 | #define _TIF_SIGDELAYED (1 << TIF_SIGDELAYED) | 104 | #define _TIF_SIGDELAYED (1 << TIF_SIGDELAYED) |
104 | #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) | 105 | #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) |
105 | #define _TIF_MCA_INIT (1 << TIF_MCA_INIT) | 106 | #define _TIF_MCA_INIT (1 << TIF_MCA_INIT) |
107 | #define _TIF_DB_DISABLED (1 << TIF_DB_DISABLED) | ||
106 | 108 | ||
107 | /* "work to do on user-return" bits */ | 109 | /* "work to do on user-return" bits */ |
108 | #define TIF_ALLWORK_MASK (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SIGDELAYED) | 110 | #define TIF_ALLWORK_MASK (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SIGDELAYED) |
diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h index 248f9aec959c..147a38dcc766 100644 --- a/include/asm-powerpc/atomic.h +++ b/include/asm-powerpc/atomic.h | |||
@@ -36,7 +36,7 @@ static __inline__ int atomic_add_return(int a, atomic_t *v) | |||
36 | int t; | 36 | int t; |
37 | 37 | ||
38 | __asm__ __volatile__( | 38 | __asm__ __volatile__( |
39 | EIEIO_ON_SMP | 39 | LWSYNC_ON_SMP |
40 | "1: lwarx %0,0,%2 # atomic_add_return\n\ | 40 | "1: lwarx %0,0,%2 # atomic_add_return\n\ |
41 | add %0,%1,%0\n" | 41 | add %0,%1,%0\n" |
42 | PPC405_ERR77(0,%2) | 42 | PPC405_ERR77(0,%2) |
@@ -72,7 +72,7 @@ static __inline__ int atomic_sub_return(int a, atomic_t *v) | |||
72 | int t; | 72 | int t; |
73 | 73 | ||
74 | __asm__ __volatile__( | 74 | __asm__ __volatile__( |
75 | EIEIO_ON_SMP | 75 | LWSYNC_ON_SMP |
76 | "1: lwarx %0,0,%2 # atomic_sub_return\n\ | 76 | "1: lwarx %0,0,%2 # atomic_sub_return\n\ |
77 | subf %0,%1,%0\n" | 77 | subf %0,%1,%0\n" |
78 | PPC405_ERR77(0,%2) | 78 | PPC405_ERR77(0,%2) |
@@ -106,7 +106,7 @@ static __inline__ int atomic_inc_return(atomic_t *v) | |||
106 | int t; | 106 | int t; |
107 | 107 | ||
108 | __asm__ __volatile__( | 108 | __asm__ __volatile__( |
109 | EIEIO_ON_SMP | 109 | LWSYNC_ON_SMP |
110 | "1: lwarx %0,0,%1 # atomic_inc_return\n\ | 110 | "1: lwarx %0,0,%1 # atomic_inc_return\n\ |
111 | addic %0,%0,1\n" | 111 | addic %0,%0,1\n" |
112 | PPC405_ERR77(0,%1) | 112 | PPC405_ERR77(0,%1) |
@@ -150,7 +150,7 @@ static __inline__ int atomic_dec_return(atomic_t *v) | |||
150 | int t; | 150 | int t; |
151 | 151 | ||
152 | __asm__ __volatile__( | 152 | __asm__ __volatile__( |
153 | EIEIO_ON_SMP | 153 | LWSYNC_ON_SMP |
154 | "1: lwarx %0,0,%1 # atomic_dec_return\n\ | 154 | "1: lwarx %0,0,%1 # atomic_dec_return\n\ |
155 | addic %0,%0,-1\n" | 155 | addic %0,%0,-1\n" |
156 | PPC405_ERR77(0,%1) | 156 | PPC405_ERR77(0,%1) |
@@ -176,19 +176,19 @@ static __inline__ int atomic_dec_return(atomic_t *v) | |||
176 | * Atomically adds @a to @v, so long as it was not @u. | 176 | * Atomically adds @a to @v, so long as it was not @u. |
177 | * Returns non-zero if @v was not @u, and zero otherwise. | 177 | * Returns non-zero if @v was not @u, and zero otherwise. |
178 | */ | 178 | */ |
179 | #define atomic_add_unless(v, a, u) \ | 179 | #define atomic_add_unless(v, a, u) \ |
180 | ({ \ | 180 | ({ \ |
181 | int c, old; \ | 181 | int c, old; \ |
182 | c = atomic_read(v); \ | 182 | c = atomic_read(v); \ |
183 | for (;;) { \ | 183 | for (;;) { \ |
184 | if (unlikely(c == (u))) \ | 184 | if (unlikely(c == (u))) \ |
185 | break; \ | 185 | break; \ |
186 | old = atomic_cmpxchg((v), c, c + (a)); \ | 186 | old = atomic_cmpxchg((v), c, c + (a)); \ |
187 | if (likely(old == c)) \ | 187 | if (likely(old == c)) \ |
188 | break; \ | 188 | break; \ |
189 | c = old; \ | 189 | c = old; \ |
190 | } \ | 190 | } \ |
191 | c != (u); \ | 191 | c != (u); \ |
192 | }) | 192 | }) |
193 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | 193 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) |
194 | 194 | ||
@@ -204,7 +204,7 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v) | |||
204 | int t; | 204 | int t; |
205 | 205 | ||
206 | __asm__ __volatile__( | 206 | __asm__ __volatile__( |
207 | EIEIO_ON_SMP | 207 | LWSYNC_ON_SMP |
208 | "1: lwarx %0,0,%1 # atomic_dec_if_positive\n\ | 208 | "1: lwarx %0,0,%1 # atomic_dec_if_positive\n\ |
209 | addic. %0,%0,-1\n\ | 209 | addic. %0,%0,-1\n\ |
210 | blt- 2f\n" | 210 | blt- 2f\n" |
@@ -253,7 +253,7 @@ static __inline__ long atomic64_add_return(long a, atomic64_t *v) | |||
253 | long t; | 253 | long t; |
254 | 254 | ||
255 | __asm__ __volatile__( | 255 | __asm__ __volatile__( |
256 | EIEIO_ON_SMP | 256 | LWSYNC_ON_SMP |
257 | "1: ldarx %0,0,%2 # atomic64_add_return\n\ | 257 | "1: ldarx %0,0,%2 # atomic64_add_return\n\ |
258 | add %0,%1,%0\n\ | 258 | add %0,%1,%0\n\ |
259 | stdcx. %0,0,%2 \n\ | 259 | stdcx. %0,0,%2 \n\ |
@@ -287,7 +287,7 @@ static __inline__ long atomic64_sub_return(long a, atomic64_t *v) | |||
287 | long t; | 287 | long t; |
288 | 288 | ||
289 | __asm__ __volatile__( | 289 | __asm__ __volatile__( |
290 | EIEIO_ON_SMP | 290 | LWSYNC_ON_SMP |
291 | "1: ldarx %0,0,%2 # atomic64_sub_return\n\ | 291 | "1: ldarx %0,0,%2 # atomic64_sub_return\n\ |
292 | subf %0,%1,%0\n\ | 292 | subf %0,%1,%0\n\ |
293 | stdcx. %0,0,%2 \n\ | 293 | stdcx. %0,0,%2 \n\ |
@@ -319,7 +319,7 @@ static __inline__ long atomic64_inc_return(atomic64_t *v) | |||
319 | long t; | 319 | long t; |
320 | 320 | ||
321 | __asm__ __volatile__( | 321 | __asm__ __volatile__( |
322 | EIEIO_ON_SMP | 322 | LWSYNC_ON_SMP |
323 | "1: ldarx %0,0,%1 # atomic64_inc_return\n\ | 323 | "1: ldarx %0,0,%1 # atomic64_inc_return\n\ |
324 | addic %0,%0,1\n\ | 324 | addic %0,%0,1\n\ |
325 | stdcx. %0,0,%1 \n\ | 325 | stdcx. %0,0,%1 \n\ |
@@ -361,7 +361,7 @@ static __inline__ long atomic64_dec_return(atomic64_t *v) | |||
361 | long t; | 361 | long t; |
362 | 362 | ||
363 | __asm__ __volatile__( | 363 | __asm__ __volatile__( |
364 | EIEIO_ON_SMP | 364 | LWSYNC_ON_SMP |
365 | "1: ldarx %0,0,%1 # atomic64_dec_return\n\ | 365 | "1: ldarx %0,0,%1 # atomic64_dec_return\n\ |
366 | addic %0,%0,-1\n\ | 366 | addic %0,%0,-1\n\ |
367 | stdcx. %0,0,%1\n\ | 367 | stdcx. %0,0,%1\n\ |
@@ -386,7 +386,7 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v) | |||
386 | long t; | 386 | long t; |
387 | 387 | ||
388 | __asm__ __volatile__( | 388 | __asm__ __volatile__( |
389 | EIEIO_ON_SMP | 389 | LWSYNC_ON_SMP |
390 | "1: ldarx %0,0,%1 # atomic64_dec_if_positive\n\ | 390 | "1: ldarx %0,0,%1 # atomic64_dec_if_positive\n\ |
391 | addic. %0,%0,-1\n\ | 391 | addic. %0,%0,-1\n\ |
392 | blt- 2f\n\ | 392 | blt- 2f\n\ |
diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h index 1996eaa8aeae..bf6941a810b8 100644 --- a/include/asm-powerpc/bitops.h +++ b/include/asm-powerpc/bitops.h | |||
@@ -112,7 +112,7 @@ static __inline__ int test_and_set_bit(unsigned long nr, | |||
112 | unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); | 112 | unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); |
113 | 113 | ||
114 | __asm__ __volatile__( | 114 | __asm__ __volatile__( |
115 | EIEIO_ON_SMP | 115 | LWSYNC_ON_SMP |
116 | "1:" PPC_LLARX "%0,0,%3 # test_and_set_bit\n" | 116 | "1:" PPC_LLARX "%0,0,%3 # test_and_set_bit\n" |
117 | "or %1,%0,%2 \n" | 117 | "or %1,%0,%2 \n" |
118 | PPC405_ERR77(0,%3) | 118 | PPC405_ERR77(0,%3) |
@@ -134,7 +134,7 @@ static __inline__ int test_and_clear_bit(unsigned long nr, | |||
134 | unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); | 134 | unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); |
135 | 135 | ||
136 | __asm__ __volatile__( | 136 | __asm__ __volatile__( |
137 | EIEIO_ON_SMP | 137 | LWSYNC_ON_SMP |
138 | "1:" PPC_LLARX "%0,0,%3 # test_and_clear_bit\n" | 138 | "1:" PPC_LLARX "%0,0,%3 # test_and_clear_bit\n" |
139 | "andc %1,%0,%2 \n" | 139 | "andc %1,%0,%2 \n" |
140 | PPC405_ERR77(0,%3) | 140 | PPC405_ERR77(0,%3) |
@@ -156,7 +156,7 @@ static __inline__ int test_and_change_bit(unsigned long nr, | |||
156 | unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); | 156 | unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); |
157 | 157 | ||
158 | __asm__ __volatile__( | 158 | __asm__ __volatile__( |
159 | EIEIO_ON_SMP | 159 | LWSYNC_ON_SMP |
160 | "1:" PPC_LLARX "%0,0,%3 # test_and_change_bit\n" | 160 | "1:" PPC_LLARX "%0,0,%3 # test_and_change_bit\n" |
161 | "xor %1,%0,%2 \n" | 161 | "xor %1,%0,%2 \n" |
162 | PPC405_ERR77(0,%3) | 162 | PPC405_ERR77(0,%3) |
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index ef6ead34a773..64210549f56b 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h | |||
@@ -19,6 +19,7 @@ | |||
19 | #define PPC_FEATURE_POWER5 0x00040000 | 19 | #define PPC_FEATURE_POWER5 0x00040000 |
20 | #define PPC_FEATURE_POWER5_PLUS 0x00020000 | 20 | #define PPC_FEATURE_POWER5_PLUS 0x00020000 |
21 | #define PPC_FEATURE_CELL 0x00010000 | 21 | #define PPC_FEATURE_CELL 0x00010000 |
22 | #define PPC_FEATURE_BOOKE 0x00008000 | ||
22 | 23 | ||
23 | #ifdef __KERNEL__ | 24 | #ifdef __KERNEL__ |
24 | #ifndef __ASSEMBLY__ | 25 | #ifndef __ASSEMBLY__ |
@@ -31,11 +32,11 @@ struct cpu_spec; | |||
31 | typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); | 32 | typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); |
32 | 33 | ||
33 | enum powerpc_oprofile_type { | 34 | enum powerpc_oprofile_type { |
34 | INVALID = 0, | 35 | PPC_OPROFILE_INVALID = 0, |
35 | RS64 = 1, | 36 | PPC_OPROFILE_RS64 = 1, |
36 | POWER4 = 2, | 37 | PPC_OPROFILE_POWER4 = 2, |
37 | G4 = 3, | 38 | PPC_OPROFILE_G4 = 3, |
38 | BOOKE = 4, | 39 | PPC_OPROFILE_BOOKE = 4, |
39 | }; | 40 | }; |
40 | 41 | ||
41 | struct cpu_spec { | 42 | struct cpu_spec { |
@@ -64,6 +65,9 @@ struct cpu_spec { | |||
64 | 65 | ||
65 | /* Processor specific oprofile operations */ | 66 | /* Processor specific oprofile operations */ |
66 | enum powerpc_oprofile_type oprofile_type; | 67 | enum powerpc_oprofile_type oprofile_type; |
68 | |||
69 | /* Name of processor class, for the ELF AT_PLATFORM entry */ | ||
70 | char *platform; | ||
67 | }; | 71 | }; |
68 | 72 | ||
69 | extern struct cpu_spec *cur_cpu_spec; | 73 | extern struct cpu_spec *cur_cpu_spec; |
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h index 45f2af6f89c4..94d228f9c6ac 100644 --- a/include/asm-powerpc/elf.h +++ b/include/asm-powerpc/elf.h | |||
@@ -221,20 +221,18 @@ extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *); | |||
221 | instruction set this cpu supports. This could be done in userspace, | 221 | instruction set this cpu supports. This could be done in userspace, |
222 | but it's not easy, and we've already done it here. */ | 222 | but it's not easy, and we've already done it here. */ |
223 | # define ELF_HWCAP (cur_cpu_spec->cpu_user_features) | 223 | # define ELF_HWCAP (cur_cpu_spec->cpu_user_features) |
224 | #ifdef __powerpc64__ | ||
225 | # define ELF_PLAT_INIT(_r, load_addr) do { \ | ||
226 | _r->gpr[2] = load_addr; \ | ||
227 | } while (0) | ||
228 | #endif /* __powerpc64__ */ | ||
229 | 224 | ||
230 | /* This yields a string that ld.so will use to load implementation | 225 | /* This yields a string that ld.so will use to load implementation |
231 | specific libraries for optimization. This is more specific in | 226 | specific libraries for optimization. This is more specific in |
232 | intent than poking at uname or /proc/cpuinfo. | 227 | intent than poking at uname or /proc/cpuinfo. */ |
233 | 228 | ||
234 | For the moment, we have only optimizations for the Intel generations, | 229 | #define ELF_PLATFORM (cur_cpu_spec->platform) |
235 | but that could change... */ | ||
236 | 230 | ||
237 | #define ELF_PLATFORM (NULL) | 231 | #ifdef __powerpc64__ |
232 | # define ELF_PLAT_INIT(_r, load_addr) do { \ | ||
233 | _r->gpr[2] = load_addr; \ | ||
234 | } while (0) | ||
235 | #endif /* __powerpc64__ */ | ||
238 | 236 | ||
239 | #ifdef __KERNEL__ | 237 | #ifdef __KERNEL__ |
240 | 238 | ||
diff --git a/include/asm-powerpc/futex.h b/include/asm-powerpc/futex.h index f0319d50b129..39e85f320a76 100644 --- a/include/asm-powerpc/futex.h +++ b/include/asm-powerpc/futex.h | |||
@@ -11,7 +11,7 @@ | |||
11 | 11 | ||
12 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ | 12 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ |
13 | __asm__ __volatile ( \ | 13 | __asm__ __volatile ( \ |
14 | SYNC_ON_SMP \ | 14 | LWSYNC_ON_SMP \ |
15 | "1: lwarx %0,0,%2\n" \ | 15 | "1: lwarx %0,0,%2\n" \ |
16 | insn \ | 16 | insn \ |
17 | PPC405_ERR77(0, %2) \ | 17 | PPC405_ERR77(0, %2) \ |
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h index da7af5a720e0..38ca9ad6110d 100644 --- a/include/asm-powerpc/hvcall.h +++ b/include/asm-powerpc/hvcall.h | |||
@@ -6,7 +6,10 @@ | |||
6 | 6 | ||
7 | #define H_Success 0 | 7 | #define H_Success 0 |
8 | #define H_Busy 1 /* Hardware busy -- retry later */ | 8 | #define H_Busy 1 /* Hardware busy -- retry later */ |
9 | #define H_Closed 2 /* Resource closed */ | ||
9 | #define H_Constrained 4 /* Resource request constrained to max allowed */ | 10 | #define H_Constrained 4 /* Resource request constrained to max allowed */ |
11 | #define H_InProgress 14 /* Kind of like busy */ | ||
12 | #define H_Continue 18 /* Returned from H_Join on success */ | ||
10 | #define H_LongBusyStartRange 9900 /* Start of long busy range */ | 13 | #define H_LongBusyStartRange 9900 /* Start of long busy range */ |
11 | #define H_LongBusyOrder1msec 9900 /* Long busy, hint that 1msec is a good time to retry */ | 14 | #define H_LongBusyOrder1msec 9900 /* Long busy, hint that 1msec is a good time to retry */ |
12 | #define H_LongBusyOrder10msec 9901 /* Long busy, hint that 10msec is a good time to retry */ | 15 | #define H_LongBusyOrder10msec 9901 /* Long busy, hint that 10msec is a good time to retry */ |
@@ -114,6 +117,8 @@ | |||
114 | #define H_REGISTER_VTERM 0x154 | 117 | #define H_REGISTER_VTERM 0x154 |
115 | #define H_FREE_VTERM 0x158 | 118 | #define H_FREE_VTERM 0x158 |
116 | #define H_POLL_PENDING 0x1D8 | 119 | #define H_POLL_PENDING 0x1D8 |
120 | #define H_JOIN 0x298 | ||
121 | #define H_ENABLE_CRQ 0x2B0 | ||
117 | 122 | ||
118 | #ifndef __ASSEMBLY__ | 123 | #ifndef __ASSEMBLY__ |
119 | 124 | ||
diff --git a/include/asm-powerpc/lppaca.h b/include/asm-powerpc/lppaca.h index ff82ea7c4829..cd9f11f1ef14 100644 --- a/include/asm-powerpc/lppaca.h +++ b/include/asm-powerpc/lppaca.h | |||
@@ -29,7 +29,9 @@ | |||
29 | //---------------------------------------------------------------------------- | 29 | //---------------------------------------------------------------------------- |
30 | #include <asm/types.h> | 30 | #include <asm/types.h> |
31 | 31 | ||
32 | struct lppaca { | 32 | /* The Hypervisor barfs if the lppaca crosses a page boundary. A 1k |
33 | * alignment is sufficient to prevent this */ | ||
34 | struct __attribute__((__aligned__(0x400))) lppaca { | ||
33 | //============================================================================= | 35 | //============================================================================= |
34 | // CACHE_LINE_1 0x0000 - 0x007F Contains read-only data | 36 | // CACHE_LINE_1 0x0000 - 0x007F Contains read-only data |
35 | // NOTE: The xDynXyz fields are fields that will be dynamically changed by | 37 | // NOTE: The xDynXyz fields are fields that will be dynamically changed by |
@@ -129,5 +131,7 @@ struct lppaca { | |||
129 | u8 pmc_save_area[256]; // PMC interrupt Area x00-xFF | 131 | u8 pmc_save_area[256]; // PMC interrupt Area x00-xFF |
130 | }; | 132 | }; |
131 | 133 | ||
134 | extern struct lppaca lppaca[]; | ||
135 | |||
132 | #endif /* __KERNEL__ */ | 136 | #endif /* __KERNEL__ */ |
133 | #endif /* _ASM_POWERPC_LPPACA_H */ | 137 | #endif /* _ASM_POWERPC_LPPACA_H */ |
diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index a64b4d425dab..c9add8f1ad94 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | register struct paca_struct *local_paca asm("r13"); | 24 | register struct paca_struct *local_paca asm("r13"); |
25 | #define get_paca() local_paca | 25 | #define get_paca() local_paca |
26 | #define get_lppaca() (get_paca()->lppaca_ptr) | ||
26 | 27 | ||
27 | struct task_struct; | 28 | struct task_struct; |
28 | 29 | ||
@@ -95,19 +96,6 @@ struct paca_struct { | |||
95 | u64 saved_r1; /* r1 save for RTAS calls */ | 96 | u64 saved_r1; /* r1 save for RTAS calls */ |
96 | u64 saved_msr; /* MSR saved here by enter_rtas */ | 97 | u64 saved_msr; /* MSR saved here by enter_rtas */ |
97 | u8 proc_enabled; /* irq soft-enable flag */ | 98 | u8 proc_enabled; /* irq soft-enable flag */ |
98 | |||
99 | /* | ||
100 | * iSeries structure which the hypervisor knows about - | ||
101 | * this structure should not cross a page boundary. | ||
102 | * The vpa_init/register_vpa call is now known to fail if the | ||
103 | * lppaca structure crosses a page boundary. | ||
104 | * The lppaca is also used on POWER5 pSeries boxes. | ||
105 | * The lppaca is 640 bytes long, and cannot readily change | ||
106 | * since the hypervisor knows its layout, so a 1kB | ||
107 | * alignment will suffice to ensure that it doesn't | ||
108 | * cross a page boundary. | ||
109 | */ | ||
110 | struct lppaca lppaca __attribute__((__aligned__(0x400))); | ||
111 | }; | 99 | }; |
112 | 100 | ||
113 | extern struct paca_struct paca[]; | 101 | extern struct paca_struct paca[]; |
diff --git a/include/asm-powerpc/ppc_asm.h b/include/asm-powerpc/ppc_asm.h index 0dc798d46ea4..ab8688d39024 100644 --- a/include/asm-powerpc/ppc_asm.h +++ b/include/asm-powerpc/ppc_asm.h | |||
@@ -156,52 +156,56 @@ n: | |||
156 | #endif | 156 | #endif |
157 | 157 | ||
158 | /* | 158 | /* |
159 | * LOADADDR( rn, name ) | 159 | * LOAD_REG_IMMEDIATE(rn, expr) |
160 | * loads the address of 'name' into 'rn' | 160 | * Loads the value of the constant expression 'expr' into register 'rn' |
161 | * using immediate instructions only. Use this when it's important not | ||
162 | * to reference other data (i.e. on ppc64 when the TOC pointer is not | ||
163 | * valid). | ||
161 | * | 164 | * |
162 | * LOADBASE( rn, name ) | 165 | * LOAD_REG_ADDR(rn, name) |
163 | * loads the address (possibly without the low 16 bits) of 'name' into 'rn' | 166 | * Loads the address of label 'name' into register 'rn'. Use this when |
164 | * suitable for base+disp addressing | 167 | * you don't particularly need immediate instructions only, but you need |
168 | * the whole address in one register (e.g. it's a structure address and | ||
169 | * you want to access various offsets within it). On ppc32 this is | ||
170 | * identical to LOAD_REG_IMMEDIATE. | ||
171 | * | ||
172 | * LOAD_REG_ADDRBASE(rn, name) | ||
173 | * ADDROFF(name) | ||
174 | * LOAD_REG_ADDRBASE loads part of the address of label 'name' into | ||
175 | * register 'rn'. ADDROFF(name) returns the remainder of the address as | ||
176 | * a constant expression. ADDROFF(name) is a signed expression < 16 bits | ||
177 | * in size, so is suitable for use directly as an offset in load and store | ||
178 | * instructions. Use this when loading/storing a single word or less as: | ||
179 | * LOAD_REG_ADDRBASE(rX, name) | ||
180 | * ld rY,ADDROFF(name)(rX) | ||
165 | */ | 181 | */ |
166 | #ifdef __powerpc64__ | 182 | #ifdef __powerpc64__ |
167 | #define LOADADDR(rn,name) \ | 183 | #define LOAD_REG_IMMEDIATE(reg,expr) \ |
168 | lis rn,name##@highest; \ | 184 | lis (reg),(expr)@highest; \ |
169 | ori rn,rn,name##@higher; \ | 185 | ori (reg),(reg),(expr)@higher; \ |
170 | rldicr rn,rn,32,31; \ | 186 | rldicr (reg),(reg),32,31; \ |
171 | oris rn,rn,name##@h; \ | 187 | oris (reg),(reg),(expr)@h; \ |
172 | ori rn,rn,name##@l | 188 | ori (reg),(reg),(expr)@l; |
173 | 189 | ||
174 | #define LOADBASE(rn,name) \ | 190 | #define LOAD_REG_ADDR(reg,name) \ |
175 | ld rn,name@got(r2) | 191 | ld (reg),name@got(r2) |
176 | 192 | ||
177 | #define OFF(name) 0 | 193 | #define LOAD_REG_ADDRBASE(reg,name) LOAD_REG_ADDR(reg,name) |
178 | 194 | #define ADDROFF(name) 0 | |
179 | #define SET_REG_TO_CONST(reg, value) \ | ||
180 | lis reg,(((value)>>48)&0xFFFF); \ | ||
181 | ori reg,reg,(((value)>>32)&0xFFFF); \ | ||
182 | rldicr reg,reg,32,31; \ | ||
183 | oris reg,reg,(((value)>>16)&0xFFFF); \ | ||
184 | ori reg,reg,((value)&0xFFFF); | ||
185 | |||
186 | #define SET_REG_TO_LABEL(reg, label) \ | ||
187 | lis reg,(label)@highest; \ | ||
188 | ori reg,reg,(label)@higher; \ | ||
189 | rldicr reg,reg,32,31; \ | ||
190 | oris reg,reg,(label)@h; \ | ||
191 | ori reg,reg,(label)@l; | ||
192 | 195 | ||
193 | /* offsets for stack frame layout */ | 196 | /* offsets for stack frame layout */ |
194 | #define LRSAVE 16 | 197 | #define LRSAVE 16 |
195 | 198 | ||
196 | #else /* 32-bit */ | 199 | #else /* 32-bit */ |
197 | #define LOADADDR(rn,name) \ | ||
198 | lis rn,name@ha; \ | ||
199 | addi rn,rn,name@l | ||
200 | 200 | ||
201 | #define LOADBASE(rn,name) \ | 201 | #define LOAD_REG_IMMEDIATE(reg,expr) \ |
202 | lis rn,name@ha | 202 | lis (reg),(expr)@ha; \ |
203 | addi (reg),(reg),(expr)@l; | ||
204 | |||
205 | #define LOAD_REG_ADDR(reg,name) LOAD_REG_IMMEDIATE(reg, name) | ||
203 | 206 | ||
204 | #define OFF(name) name@l | 207 | #define LOAD_REG_ADDRBASE(reg, name) lis (reg),name@ha |
208 | #define ADDROFF(name) name@l | ||
205 | 209 | ||
206 | /* offsets for stack frame layout */ | 210 | /* offsets for stack frame layout */ |
207 | #define LRSAVE 4 | 211 | #define LRSAVE 4 |
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 329e9bf62260..5b2bd4eefb01 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h | |||
@@ -87,6 +87,7 @@ struct device_node { | |||
87 | char *full_name; | 87 | char *full_name; |
88 | 88 | ||
89 | struct property *properties; | 89 | struct property *properties; |
90 | struct property *deadprops; /* removed properties */ | ||
90 | struct device_node *parent; | 91 | struct device_node *parent; |
91 | struct device_node *child; | 92 | struct device_node *child; |
92 | struct device_node *sibling; | 93 | struct device_node *sibling; |
@@ -135,6 +136,9 @@ extern struct device_node *of_find_all_nodes(struct device_node *prev); | |||
135 | extern struct device_node *of_get_parent(const struct device_node *node); | 136 | extern struct device_node *of_get_parent(const struct device_node *node); |
136 | extern struct device_node *of_get_next_child(const struct device_node *node, | 137 | extern struct device_node *of_get_next_child(const struct device_node *node, |
137 | struct device_node *prev); | 138 | struct device_node *prev); |
139 | extern struct property *of_find_property(struct device_node *np, | ||
140 | const char *name, | ||
141 | int *lenp); | ||
138 | extern struct device_node *of_node_get(struct device_node *node); | 142 | extern struct device_node *of_node_get(struct device_node *node); |
139 | extern void of_node_put(struct device_node *node); | 143 | extern void of_node_put(struct device_node *node); |
140 | 144 | ||
@@ -164,6 +168,10 @@ extern int prom_n_size_cells(struct device_node* np); | |||
164 | extern int prom_n_intr_cells(struct device_node* np); | 168 | extern int prom_n_intr_cells(struct device_node* np); |
165 | extern void prom_get_irq_senses(unsigned char *senses, int off, int max); | 169 | extern void prom_get_irq_senses(unsigned char *senses, int off, int max); |
166 | extern int prom_add_property(struct device_node* np, struct property* prop); | 170 | extern int prom_add_property(struct device_node* np, struct property* prop); |
171 | extern int prom_remove_property(struct device_node *np, struct property *prop); | ||
172 | extern int prom_update_property(struct device_node *np, | ||
173 | struct property *newprop, | ||
174 | struct property *oldprop); | ||
167 | 175 | ||
168 | #ifdef CONFIG_PPC32 | 176 | #ifdef CONFIG_PPC32 |
169 | /* | 177 | /* |
diff --git a/include/asm-powerpc/spinlock.h b/include/asm-powerpc/spinlock.h index 754900901cd8..895cb6d3a42a 100644 --- a/include/asm-powerpc/spinlock.h +++ b/include/asm-powerpc/spinlock.h | |||
@@ -46,7 +46,7 @@ static __inline__ unsigned long __spin_trylock(raw_spinlock_t *lock) | |||
46 | 46 | ||
47 | token = LOCK_TOKEN; | 47 | token = LOCK_TOKEN; |
48 | __asm__ __volatile__( | 48 | __asm__ __volatile__( |
49 | "1: lwarx %0,0,%2 # __spin_trylock\n\ | 49 | "1: lwarx %0,0,%2\n\ |
50 | cmpwi 0,%0,0\n\ | 50 | cmpwi 0,%0,0\n\ |
51 | bne- 2f\n\ | 51 | bne- 2f\n\ |
52 | stwcx. %1,0,%2\n\ | 52 | stwcx. %1,0,%2\n\ |
@@ -80,7 +80,7 @@ static int __inline__ __raw_spin_trylock(raw_spinlock_t *lock) | |||
80 | 80 | ||
81 | #if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) | 81 | #if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) |
82 | /* We only yield to the hypervisor if we are in shared processor mode */ | 82 | /* We only yield to the hypervisor if we are in shared processor mode */ |
83 | #define SHARED_PROCESSOR (get_paca()->lppaca.shared_proc) | 83 | #define SHARED_PROCESSOR (get_lppaca()->shared_proc) |
84 | extern void __spin_yield(raw_spinlock_t *lock); | 84 | extern void __spin_yield(raw_spinlock_t *lock); |
85 | extern void __rw_yield(raw_rwlock_t *lock); | 85 | extern void __rw_yield(raw_rwlock_t *lock); |
86 | #else /* SPLPAR || ISERIES */ | 86 | #else /* SPLPAR || ISERIES */ |
@@ -124,8 +124,8 @@ static void __inline__ __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long | |||
124 | 124 | ||
125 | static __inline__ void __raw_spin_unlock(raw_spinlock_t *lock) | 125 | static __inline__ void __raw_spin_unlock(raw_spinlock_t *lock) |
126 | { | 126 | { |
127 | __asm__ __volatile__(SYNC_ON_SMP" # __raw_spin_unlock" | 127 | __asm__ __volatile__("# __raw_spin_unlock\n\t" |
128 | : : :"memory"); | 128 | LWSYNC_ON_SMP: : :"memory"); |
129 | lock->slock = 0; | 129 | lock->slock = 0; |
130 | } | 130 | } |
131 | 131 | ||
@@ -167,7 +167,7 @@ static long __inline__ __read_trylock(raw_rwlock_t *rw) | |||
167 | long tmp; | 167 | long tmp; |
168 | 168 | ||
169 | __asm__ __volatile__( | 169 | __asm__ __volatile__( |
170 | "1: lwarx %0,0,%1 # read_trylock\n" | 170 | "1: lwarx %0,0,%1\n" |
171 | __DO_SIGN_EXTEND | 171 | __DO_SIGN_EXTEND |
172 | " addic. %0,%0,1\n\ | 172 | " addic. %0,%0,1\n\ |
173 | ble- 2f\n" | 173 | ble- 2f\n" |
@@ -192,7 +192,7 @@ static __inline__ long __write_trylock(raw_rwlock_t *rw) | |||
192 | 192 | ||
193 | token = WRLOCK_TOKEN; | 193 | token = WRLOCK_TOKEN; |
194 | __asm__ __volatile__( | 194 | __asm__ __volatile__( |
195 | "1: lwarx %0,0,%2 # write_trylock\n\ | 195 | "1: lwarx %0,0,%2\n\ |
196 | cmpwi 0,%0,0\n\ | 196 | cmpwi 0,%0,0\n\ |
197 | bne- 2f\n" | 197 | bne- 2f\n" |
198 | PPC405_ERR77(0,%1) | 198 | PPC405_ERR77(0,%1) |
@@ -249,8 +249,9 @@ static void __inline__ __raw_read_unlock(raw_rwlock_t *rw) | |||
249 | long tmp; | 249 | long tmp; |
250 | 250 | ||
251 | __asm__ __volatile__( | 251 | __asm__ __volatile__( |
252 | "eieio # read_unlock\n\ | 252 | "# read_unlock\n\t" |
253 | 1: lwarx %0,0,%1\n\ | 253 | LWSYNC_ON_SMP |
254 | "1: lwarx %0,0,%1\n\ | ||
254 | addic %0,%0,-1\n" | 255 | addic %0,%0,-1\n" |
255 | PPC405_ERR77(0,%1) | 256 | PPC405_ERR77(0,%1) |
256 | " stwcx. %0,0,%1\n\ | 257 | " stwcx. %0,0,%1\n\ |
@@ -262,8 +263,8 @@ static void __inline__ __raw_read_unlock(raw_rwlock_t *rw) | |||
262 | 263 | ||
263 | static __inline__ void __raw_write_unlock(raw_rwlock_t *rw) | 264 | static __inline__ void __raw_write_unlock(raw_rwlock_t *rw) |
264 | { | 265 | { |
265 | __asm__ __volatile__(SYNC_ON_SMP" # write_unlock" | 266 | __asm__ __volatile__("# write_unlock\n\t" |
266 | : : :"memory"); | 267 | LWSYNC_ON_SMP: : :"memory"); |
267 | rw->lock = 0; | 268 | rw->lock = 0; |
268 | } | 269 | } |
269 | 270 | ||
diff --git a/include/asm-powerpc/synch.h b/include/asm-powerpc/synch.h index 794870ab8fd3..c90d9d9aae72 100644 --- a/include/asm-powerpc/synch.h +++ b/include/asm-powerpc/synch.h | |||
@@ -2,6 +2,8 @@ | |||
2 | #define _ASM_POWERPC_SYNCH_H | 2 | #define _ASM_POWERPC_SYNCH_H |
3 | #ifdef __KERNEL__ | 3 | #ifdef __KERNEL__ |
4 | 4 | ||
5 | #include <linux/stringify.h> | ||
6 | |||
5 | #ifdef __powerpc64__ | 7 | #ifdef __powerpc64__ |
6 | #define __SUBARCH_HAS_LWSYNC | 8 | #define __SUBARCH_HAS_LWSYNC |
7 | #endif | 9 | #endif |
@@ -12,20 +14,12 @@ | |||
12 | # define LWSYNC sync | 14 | # define LWSYNC sync |
13 | #endif | 15 | #endif |
14 | 16 | ||
15 | |||
16 | /* | ||
17 | * Arguably the bitops and *xchg operations don't imply any memory barrier | ||
18 | * or SMP ordering, but in fact a lot of drivers expect them to imply | ||
19 | * both, since they do on x86 cpus. | ||
20 | */ | ||
21 | #ifdef CONFIG_SMP | 17 | #ifdef CONFIG_SMP |
22 | #define EIEIO_ON_SMP "eieio\n" | ||
23 | #define ISYNC_ON_SMP "\n\tisync" | 18 | #define ISYNC_ON_SMP "\n\tisync" |
24 | #define SYNC_ON_SMP __stringify(LWSYNC) "\n" | 19 | #define LWSYNC_ON_SMP __stringify(LWSYNC) "\n" |
25 | #else | 20 | #else |
26 | #define EIEIO_ON_SMP | ||
27 | #define ISYNC_ON_SMP | 21 | #define ISYNC_ON_SMP |
28 | #define SYNC_ON_SMP | 22 | #define LWSYNC_ON_SMP |
29 | #endif | 23 | #endif |
30 | 24 | ||
31 | static inline void eieio(void) | 25 | static inline void eieio(void) |
@@ -38,14 +32,5 @@ static inline void isync(void) | |||
38 | __asm__ __volatile__ ("isync" : : : "memory"); | 32 | __asm__ __volatile__ ("isync" : : : "memory"); |
39 | } | 33 | } |
40 | 34 | ||
41 | #ifdef CONFIG_SMP | ||
42 | #define eieio_on_smp() eieio() | ||
43 | #define isync_on_smp() isync() | ||
44 | #else | ||
45 | #define eieio_on_smp() __asm__ __volatile__("": : :"memory") | ||
46 | #define isync_on_smp() __asm__ __volatile__("": : :"memory") | ||
47 | #endif | ||
48 | |||
49 | #endif /* __KERNEL__ */ | 35 | #endif /* __KERNEL__ */ |
50 | #endif /* _ASM_POWERPC_SYNCH_H */ | 36 | #endif /* _ASM_POWERPC_SYNCH_H */ |
51 | |||
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index 9b822afa7d0e..d9bf53653b10 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h | |||
@@ -212,7 +212,7 @@ __xchg_u32(volatile void *p, unsigned long val) | |||
212 | unsigned long prev; | 212 | unsigned long prev; |
213 | 213 | ||
214 | __asm__ __volatile__( | 214 | __asm__ __volatile__( |
215 | EIEIO_ON_SMP | 215 | LWSYNC_ON_SMP |
216 | "1: lwarx %0,0,%2 \n" | 216 | "1: lwarx %0,0,%2 \n" |
217 | PPC405_ERR77(0,%2) | 217 | PPC405_ERR77(0,%2) |
218 | " stwcx. %3,0,%2 \n\ | 218 | " stwcx. %3,0,%2 \n\ |
@@ -232,7 +232,7 @@ __xchg_u64(volatile void *p, unsigned long val) | |||
232 | unsigned long prev; | 232 | unsigned long prev; |
233 | 233 | ||
234 | __asm__ __volatile__( | 234 | __asm__ __volatile__( |
235 | EIEIO_ON_SMP | 235 | LWSYNC_ON_SMP |
236 | "1: ldarx %0,0,%2 \n" | 236 | "1: ldarx %0,0,%2 \n" |
237 | PPC405_ERR77(0,%2) | 237 | PPC405_ERR77(0,%2) |
238 | " stdcx. %3,0,%2 \n\ | 238 | " stdcx. %3,0,%2 \n\ |
@@ -287,7 +287,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new) | |||
287 | unsigned int prev; | 287 | unsigned int prev; |
288 | 288 | ||
289 | __asm__ __volatile__ ( | 289 | __asm__ __volatile__ ( |
290 | EIEIO_ON_SMP | 290 | LWSYNC_ON_SMP |
291 | "1: lwarx %0,0,%2 # __cmpxchg_u32\n\ | 291 | "1: lwarx %0,0,%2 # __cmpxchg_u32\n\ |
292 | cmpw 0,%0,%3\n\ | 292 | cmpw 0,%0,%3\n\ |
293 | bne- 2f\n" | 293 | bne- 2f\n" |
@@ -311,7 +311,7 @@ __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) | |||
311 | unsigned long prev; | 311 | unsigned long prev; |
312 | 312 | ||
313 | __asm__ __volatile__ ( | 313 | __asm__ __volatile__ ( |
314 | EIEIO_ON_SMP | 314 | LWSYNC_ON_SMP |
315 | "1: ldarx %0,0,%2 # __cmpxchg_u64\n\ | 315 | "1: ldarx %0,0,%2 # __cmpxchg_u64\n\ |
316 | cmpd 0,%0,%3\n\ | 316 | cmpd 0,%0,%3\n\ |
317 | bne- 2f\n\ | 317 | bne- 2f\n\ |
diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h index d9b86a17271b..baddc9ab57ad 100644 --- a/include/asm-powerpc/time.h +++ b/include/asm-powerpc/time.h | |||
@@ -175,11 +175,10 @@ static inline void set_dec(int val) | |||
175 | set_dec_cpu6(val); | 175 | set_dec_cpu6(val); |
176 | #else | 176 | #else |
177 | #ifdef CONFIG_PPC_ISERIES | 177 | #ifdef CONFIG_PPC_ISERIES |
178 | struct paca_struct *lpaca = get_paca(); | ||
179 | int cur_dec; | 178 | int cur_dec; |
180 | 179 | ||
181 | if (lpaca->lppaca.shared_proc) { | 180 | if (get_lppaca()->shared_proc) { |
182 | lpaca->lppaca.virtual_decr = val; | 181 | get_lppaca()->virtual_decr = val; |
183 | cur_dec = get_dec(); | 182 | cur_dec = get_dec(); |
184 | if (cur_dec > val) | 183 | if (cur_dec > val) |
185 | HvCall_setVirtualDecr(); | 184 | HvCall_setVirtualDecr(); |
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index e6ee2d95da7a..323924edb26a 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -216,6 +216,7 @@ extern void dump_stack(void); | |||
216 | ((unsigned char *)&addr)[1], \ | 216 | ((unsigned char *)&addr)[1], \ |
217 | ((unsigned char *)&addr)[2], \ | 217 | ((unsigned char *)&addr)[2], \ |
218 | ((unsigned char *)&addr)[3] | 218 | ((unsigned char *)&addr)[3] |
219 | #define NIPQUAD_FMT "%u.%u.%u.%u" | ||
219 | 220 | ||
220 | #define NIP6(addr) \ | 221 | #define NIP6(addr) \ |
221 | ntohs((addr).s6_addr16[0]), \ | 222 | ntohs((addr).s6_addr16[0]), \ |
@@ -226,6 +227,7 @@ extern void dump_stack(void); | |||
226 | ntohs((addr).s6_addr16[5]), \ | 227 | ntohs((addr).s6_addr16[5]), \ |
227 | ntohs((addr).s6_addr16[6]), \ | 228 | ntohs((addr).s6_addr16[6]), \ |
228 | ntohs((addr).s6_addr16[7]) | 229 | ntohs((addr).s6_addr16[7]) |
230 | #define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" | ||
229 | 231 | ||
230 | #if defined(__LITTLE_ENDIAN) | 232 | #if defined(__LITTLE_ENDIAN) |
231 | #define HIPQUAD(addr) \ | 233 | #define HIPQUAD(addr) \ |
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h index 6d39b518486b..3ff88c878308 100644 --- a/include/linux/netfilter/nf_conntrack_common.h +++ b/include/linux/netfilter/nf_conntrack_common.h | |||
@@ -154,6 +154,9 @@ struct ip_conntrack_stat | |||
154 | unsigned int expect_delete; | 154 | unsigned int expect_delete; |
155 | }; | 155 | }; |
156 | 156 | ||
157 | /* call to create an explicit dependency on nf_conntrack. */ | ||
158 | extern void need_conntrack(void); | ||
159 | |||
157 | #endif /* __KERNEL__ */ | 160 | #endif /* __KERNEL__ */ |
158 | 161 | ||
159 | #endif /* _NF_CONNTRACK_COMMON_H */ | 162 | #endif /* _NF_CONNTRACK_COMMON_H */ |
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h new file mode 100644 index 000000000000..472f04834809 --- /dev/null +++ b/include/linux/netfilter/x_tables.h | |||
@@ -0,0 +1,224 @@ | |||
1 | #ifndef _X_TABLES_H | ||
2 | #define _X_TABLES_H | ||
3 | |||
4 | #define XT_FUNCTION_MAXNAMELEN 30 | ||
5 | #define XT_TABLE_MAXNAMELEN 32 | ||
6 | |||
7 | /* The argument to IPT_SO_GET_REVISION_*. Returns highest revision | ||
8 | * kernel supports, if >= revision. */ | ||
9 | struct xt_get_revision | ||
10 | { | ||
11 | char name[XT_FUNCTION_MAXNAMELEN-1]; | ||
12 | |||
13 | u_int8_t revision; | ||
14 | }; | ||
15 | |||
16 | /* CONTINUE verdict for targets */ | ||
17 | #define XT_CONTINUE 0xFFFFFFFF | ||
18 | |||
19 | /* For standard target */ | ||
20 | #define XT_RETURN (-NF_REPEAT - 1) | ||
21 | |||
22 | #define XT_ALIGN(s) (((s) + (__alignof__(void *)-1)) & ~(__alignof__(void *)-1)) | ||
23 | |||
24 | /* Standard return verdict, or do jump. */ | ||
25 | #define XT_STANDARD_TARGET "" | ||
26 | /* Error verdict. */ | ||
27 | #define XT_ERROR_TARGET "ERROR" | ||
28 | |||
29 | /* | ||
30 | * New IP firewall options for [gs]etsockopt at the RAW IP level. | ||
31 | * Unlike BSD Linux inherits IP options so you don't have to use a raw | ||
32 | * socket for this. Instead we check rights in the calls. */ | ||
33 | #define XT_BASE_CTL 64 /* base for firewall socket options */ | ||
34 | |||
35 | #define XT_SO_SET_REPLACE (XT_BASE_CTL) | ||
36 | #define XT_SO_SET_ADD_COUNTERS (XT_BASE_CTL + 1) | ||
37 | #define XT_SO_SET_MAX XT_SO_SET_ADD_COUNTERS | ||
38 | |||
39 | #define XT_SO_GET_INFO (XT_BASE_CTL) | ||
40 | #define XT_SO_GET_ENTRIES (XT_BASE_CTL + 1) | ||
41 | #define XT_SO_GET_REVISION_MATCH (XT_BASE_CTL + 2) | ||
42 | #define XT_SO_GET_REVISION_TARGET (XT_BASE_CTL + 3) | ||
43 | #define XT_SO_GET_MAX XT_SO_GET_REVISION_TARGET | ||
44 | |||
45 | #define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) | ||
46 | #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) | ||
47 | |||
48 | struct xt_counters | ||
49 | { | ||
50 | u_int64_t pcnt, bcnt; /* Packet and byte counters */ | ||
51 | }; | ||
52 | |||
53 | /* The argument to IPT_SO_ADD_COUNTERS. */ | ||
54 | struct xt_counters_info | ||
55 | { | ||
56 | /* Which table. */ | ||
57 | char name[XT_TABLE_MAXNAMELEN]; | ||
58 | |||
59 | unsigned int num_counters; | ||
60 | |||
61 | /* The counters (actually `number' of these). */ | ||
62 | struct xt_counters counters[0]; | ||
63 | }; | ||
64 | |||
65 | #define XT_INV_PROTO 0x40 /* Invert the sense of PROTO. */ | ||
66 | |||
67 | #ifdef __KERNEL__ | ||
68 | |||
69 | #include <linux/netdevice.h> | ||
70 | |||
71 | #define ASSERT_READ_LOCK(x) | ||
72 | #define ASSERT_WRITE_LOCK(x) | ||
73 | #include <linux/netfilter_ipv4/listhelp.h> | ||
74 | |||
75 | struct xt_match | ||
76 | { | ||
77 | struct list_head list; | ||
78 | |||
79 | const char name[XT_FUNCTION_MAXNAMELEN-1]; | ||
80 | |||
81 | u_int8_t revision; | ||
82 | |||
83 | /* Return true or false: return FALSE and set *hotdrop = 1 to | ||
84 | force immediate packet drop. */ | ||
85 | /* Arguments changed since 2.6.9, as this must now handle | ||
86 | non-linear skb, using skb_header_pointer and | ||
87 | skb_ip_make_writable. */ | ||
88 | int (*match)(const struct sk_buff *skb, | ||
89 | const struct net_device *in, | ||
90 | const struct net_device *out, | ||
91 | const void *matchinfo, | ||
92 | int offset, | ||
93 | unsigned int protoff, | ||
94 | int *hotdrop); | ||
95 | |||
96 | /* Called when user tries to insert an entry of this type. */ | ||
97 | /* Should return true or false. */ | ||
98 | int (*checkentry)(const char *tablename, | ||
99 | const void *ip, | ||
100 | void *matchinfo, | ||
101 | unsigned int matchinfosize, | ||
102 | unsigned int hook_mask); | ||
103 | |||
104 | /* Called when entry of this type deleted. */ | ||
105 | void (*destroy)(void *matchinfo, unsigned int matchinfosize); | ||
106 | |||
107 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
108 | struct module *me; | ||
109 | }; | ||
110 | |||
111 | /* Registration hooks for targets. */ | ||
112 | struct xt_target | ||
113 | { | ||
114 | struct list_head list; | ||
115 | |||
116 | const char name[XT_FUNCTION_MAXNAMELEN-1]; | ||
117 | |||
118 | u_int8_t revision; | ||
119 | |||
120 | /* Returns verdict. Argument order changed since 2.6.9, as this | ||
121 | must now handle non-linear skbs, using skb_copy_bits and | ||
122 | skb_ip_make_writable. */ | ||
123 | unsigned int (*target)(struct sk_buff **pskb, | ||
124 | const struct net_device *in, | ||
125 | const struct net_device *out, | ||
126 | unsigned int hooknum, | ||
127 | const void *targinfo, | ||
128 | void *userdata); | ||
129 | |||
130 | /* Called when user tries to insert an entry of this type: | ||
131 | hook_mask is a bitmask of hooks from which it can be | ||
132 | called. */ | ||
133 | /* Should return true or false. */ | ||
134 | int (*checkentry)(const char *tablename, | ||
135 | const void *entry, | ||
136 | void *targinfo, | ||
137 | unsigned int targinfosize, | ||
138 | unsigned int hook_mask); | ||
139 | |||
140 | /* Called when entry of this type deleted. */ | ||
141 | void (*destroy)(void *targinfo, unsigned int targinfosize); | ||
142 | |||
143 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
144 | struct module *me; | ||
145 | }; | ||
146 | |||
147 | /* Furniture shopping... */ | ||
148 | struct xt_table | ||
149 | { | ||
150 | struct list_head list; | ||
151 | |||
152 | /* A unique name... */ | ||
153 | char name[XT_TABLE_MAXNAMELEN]; | ||
154 | |||
155 | /* What hooks you will enter on */ | ||
156 | unsigned int valid_hooks; | ||
157 | |||
158 | /* Lock for the curtain */ | ||
159 | rwlock_t lock; | ||
160 | |||
161 | /* Man behind the curtain... */ | ||
162 | //struct ip6t_table_info *private; | ||
163 | void *private; | ||
164 | |||
165 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
166 | struct module *me; | ||
167 | |||
168 | int af; /* address/protocol family */ | ||
169 | }; | ||
170 | |||
171 | #include <linux/netfilter_ipv4.h> | ||
172 | |||
173 | /* The table itself */ | ||
174 | struct xt_table_info | ||
175 | { | ||
176 | /* Size per table */ | ||
177 | unsigned int size; | ||
178 | /* Number of entries: FIXME. --RR */ | ||
179 | unsigned int number; | ||
180 | /* Initial number of entries. Needed for module usage count */ | ||
181 | unsigned int initial_entries; | ||
182 | |||
183 | /* Entry points and underflows */ | ||
184 | unsigned int hook_entry[NF_IP_NUMHOOKS]; | ||
185 | unsigned int underflow[NF_IP_NUMHOOKS]; | ||
186 | |||
187 | /* ipt_entry tables: one per CPU */ | ||
188 | char *entries[NR_CPUS]; | ||
189 | }; | ||
190 | |||
191 | extern int xt_register_target(int af, struct xt_target *target); | ||
192 | extern void xt_unregister_target(int af, struct xt_target *target); | ||
193 | extern int xt_register_match(int af, struct xt_match *target); | ||
194 | extern void xt_unregister_match(int af, struct xt_match *target); | ||
195 | |||
196 | extern int xt_register_table(struct xt_table *table, | ||
197 | struct xt_table_info *bootstrap, | ||
198 | struct xt_table_info *newinfo); | ||
199 | extern void *xt_unregister_table(struct xt_table *table); | ||
200 | |||
201 | extern struct xt_table_info *xt_replace_table(struct xt_table *table, | ||
202 | unsigned int num_counters, | ||
203 | struct xt_table_info *newinfo, | ||
204 | int *error); | ||
205 | |||
206 | extern struct xt_match *xt_find_match(int af, const char *name, u8 revision); | ||
207 | extern struct xt_target *xt_find_target(int af, const char *name, u8 revision); | ||
208 | extern struct xt_target *xt_request_find_target(int af, const char *name, | ||
209 | u8 revision); | ||
210 | extern int xt_find_revision(int af, const char *name, u8 revision, int target, | ||
211 | int *err); | ||
212 | |||
213 | extern struct xt_table *xt_find_table_lock(int af, const char *name); | ||
214 | extern void xt_table_unlock(struct xt_table *t); | ||
215 | |||
216 | extern int xt_proto_init(int af); | ||
217 | extern void xt_proto_fini(int af); | ||
218 | |||
219 | extern struct xt_table_info *xt_alloc_table_info(unsigned int size); | ||
220 | extern void xt_free_table_info(struct xt_table_info *info); | ||
221 | |||
222 | #endif /* __KERNEL__ */ | ||
223 | |||
224 | #endif /* _X_TABLES_H */ | ||
diff --git a/include/linux/netfilter/xt_CLASSIFY.h b/include/linux/netfilter/xt_CLASSIFY.h new file mode 100644 index 000000000000..58111355255d --- /dev/null +++ b/include/linux/netfilter/xt_CLASSIFY.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _XT_CLASSIFY_H | ||
2 | #define _XT_CLASSIFY_H | ||
3 | |||
4 | struct xt_classify_target_info { | ||
5 | u_int32_t priority; | ||
6 | }; | ||
7 | |||
8 | #endif /*_XT_CLASSIFY_H */ | ||
diff --git a/include/linux/netfilter/xt_CONNMARK.h b/include/linux/netfilter/xt_CONNMARK.h new file mode 100644 index 000000000000..9f744689fffc --- /dev/null +++ b/include/linux/netfilter/xt_CONNMARK.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef _XT_CONNMARK_H_target | ||
2 | #define _XT_CONNMARK_H_target | ||
3 | |||
4 | /* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> | ||
5 | * by Henrik Nordstrom <hno@marasystems.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | enum { | ||
14 | XT_CONNMARK_SET = 0, | ||
15 | XT_CONNMARK_SAVE, | ||
16 | XT_CONNMARK_RESTORE | ||
17 | }; | ||
18 | |||
19 | struct xt_connmark_target_info { | ||
20 | unsigned long mark; | ||
21 | unsigned long mask; | ||
22 | u_int8_t mode; | ||
23 | }; | ||
24 | |||
25 | #endif /*_XT_CONNMARK_H_target*/ | ||
diff --git a/include/linux/netfilter/xt_MARK.h b/include/linux/netfilter/xt_MARK.h new file mode 100644 index 000000000000..b021e93ee5d6 --- /dev/null +++ b/include/linux/netfilter/xt_MARK.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #ifndef _XT_MARK_H_target | ||
2 | #define _XT_MARK_H_target | ||
3 | |||
4 | /* Version 0 */ | ||
5 | struct xt_mark_target_info { | ||
6 | unsigned long mark; | ||
7 | }; | ||
8 | |||
9 | /* Version 1 */ | ||
10 | enum { | ||
11 | XT_MARK_SET=0, | ||
12 | XT_MARK_AND, | ||
13 | XT_MARK_OR, | ||
14 | }; | ||
15 | |||
16 | struct xt_mark_target_info_v1 { | ||
17 | unsigned long mark; | ||
18 | u_int8_t mode; | ||
19 | }; | ||
20 | |||
21 | #endif /*_XT_MARK_H_target */ | ||
diff --git a/include/linux/netfilter/xt_NFQUEUE.h b/include/linux/netfilter/xt_NFQUEUE.h new file mode 100644 index 000000000000..9a9af79f74d2 --- /dev/null +++ b/include/linux/netfilter/xt_NFQUEUE.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* iptables module for using NFQUEUE mechanism | ||
2 | * | ||
3 | * (C) 2005 Harald Welte <laforge@netfilter.org> | ||
4 | * | ||
5 | * This software is distributed under GNU GPL v2, 1991 | ||
6 | * | ||
7 | */ | ||
8 | #ifndef _XT_NFQ_TARGET_H | ||
9 | #define _XT_NFQ_TARGET_H | ||
10 | |||
11 | /* target info */ | ||
12 | struct xt_NFQ_info { | ||
13 | u_int16_t queuenum; | ||
14 | }; | ||
15 | |||
16 | #endif /* _XT_NFQ_TARGET_H */ | ||
diff --git a/include/linux/netfilter/xt_comment.h b/include/linux/netfilter/xt_comment.h new file mode 100644 index 000000000000..eacfedc6b5d0 --- /dev/null +++ b/include/linux/netfilter/xt_comment.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef _XT_COMMENT_H | ||
2 | #define _XT_COMMENT_H | ||
3 | |||
4 | #define XT_MAX_COMMENT_LEN 256 | ||
5 | |||
6 | struct xt_comment_info { | ||
7 | unsigned char comment[XT_MAX_COMMENT_LEN]; | ||
8 | }; | ||
9 | |||
10 | #endif /* XT_COMMENT_H */ | ||
diff --git a/include/linux/netfilter/xt_connbytes.h b/include/linux/netfilter/xt_connbytes.h new file mode 100644 index 000000000000..c022c989754d --- /dev/null +++ b/include/linux/netfilter/xt_connbytes.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef _XT_CONNBYTES_H | ||
2 | #define _XT_CONNBYTES_H | ||
3 | |||
4 | enum xt_connbytes_what { | ||
5 | XT_CONNBYTES_PKTS, | ||
6 | XT_CONNBYTES_BYTES, | ||
7 | XT_CONNBYTES_AVGPKT, | ||
8 | }; | ||
9 | |||
10 | enum xt_connbytes_direction { | ||
11 | XT_CONNBYTES_DIR_ORIGINAL, | ||
12 | XT_CONNBYTES_DIR_REPLY, | ||
13 | XT_CONNBYTES_DIR_BOTH, | ||
14 | }; | ||
15 | |||
16 | struct xt_connbytes_info | ||
17 | { | ||
18 | struct { | ||
19 | aligned_u64 from; /* count to be matched */ | ||
20 | aligned_u64 to; /* count to be matched */ | ||
21 | } count; | ||
22 | u_int8_t what; /* ipt_connbytes_what */ | ||
23 | u_int8_t direction; /* ipt_connbytes_direction */ | ||
24 | }; | ||
25 | #endif | ||
diff --git a/include/linux/netfilter/xt_connmark.h b/include/linux/netfilter/xt_connmark.h new file mode 100644 index 000000000000..c592f6ae0883 --- /dev/null +++ b/include/linux/netfilter/xt_connmark.h | |||
@@ -0,0 +1,18 @@ | |||
1 | #ifndef _XT_CONNMARK_H | ||
2 | #define _XT_CONNMARK_H | ||
3 | |||
4 | /* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> | ||
5 | * by Henrik Nordstrom <hno@marasystems.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | struct xt_connmark_info { | ||
14 | unsigned long mark, mask; | ||
15 | u_int8_t invert; | ||
16 | }; | ||
17 | |||
18 | #endif /*_XT_CONNMARK_H*/ | ||
diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h new file mode 100644 index 000000000000..34f63cf2e293 --- /dev/null +++ b/include/linux/netfilter/xt_conntrack.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* Header file for kernel module to match connection tracking information. | ||
2 | * GPL (C) 2001 Marc Boucher (marc@mbsi.ca). | ||
3 | */ | ||
4 | |||
5 | #ifndef _XT_CONNTRACK_H | ||
6 | #define _XT_CONNTRACK_H | ||
7 | |||
8 | #include <linux/netfilter/nf_conntrack_tuple_common.h> | ||
9 | #include <linux/in.h> | ||
10 | |||
11 | #define XT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) | ||
12 | #define XT_CONNTRACK_STATE_INVALID (1 << 0) | ||
13 | |||
14 | #define XT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1)) | ||
15 | #define XT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2)) | ||
16 | #define XT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3)) | ||
17 | |||
18 | /* flags, invflags: */ | ||
19 | #define XT_CONNTRACK_STATE 0x01 | ||
20 | #define XT_CONNTRACK_PROTO 0x02 | ||
21 | #define XT_CONNTRACK_ORIGSRC 0x04 | ||
22 | #define XT_CONNTRACK_ORIGDST 0x08 | ||
23 | #define XT_CONNTRACK_REPLSRC 0x10 | ||
24 | #define XT_CONNTRACK_REPLDST 0x20 | ||
25 | #define XT_CONNTRACK_STATUS 0x40 | ||
26 | #define XT_CONNTRACK_EXPIRES 0x80 | ||
27 | |||
28 | /* This is exposed to userspace, so remains frozen in time. */ | ||
29 | struct ip_conntrack_old_tuple | ||
30 | { | ||
31 | struct { | ||
32 | __u32 ip; | ||
33 | union { | ||
34 | __u16 all; | ||
35 | } u; | ||
36 | } src; | ||
37 | |||
38 | struct { | ||
39 | __u32 ip; | ||
40 | union { | ||
41 | __u16 all; | ||
42 | } u; | ||
43 | |||
44 | /* The protocol. */ | ||
45 | u16 protonum; | ||
46 | } dst; | ||
47 | }; | ||
48 | |||
49 | struct xt_conntrack_info | ||
50 | { | ||
51 | unsigned int statemask, statusmask; | ||
52 | |||
53 | struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX]; | ||
54 | struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX]; | ||
55 | |||
56 | unsigned long expires_min, expires_max; | ||
57 | |||
58 | /* Flags word */ | ||
59 | u_int8_t flags; | ||
60 | /* Inverse flags */ | ||
61 | u_int8_t invflags; | ||
62 | }; | ||
63 | #endif /*_XT_CONNTRACK_H*/ | ||
diff --git a/include/linux/netfilter/xt_dccp.h b/include/linux/netfilter/xt_dccp.h new file mode 100644 index 000000000000..e0221b9d32cb --- /dev/null +++ b/include/linux/netfilter/xt_dccp.h | |||
@@ -0,0 +1,23 @@ | |||
1 | #ifndef _XT_DCCP_H_ | ||
2 | #define _XT_DCCP_H_ | ||
3 | |||
4 | #define XT_DCCP_SRC_PORTS 0x01 | ||
5 | #define XT_DCCP_DEST_PORTS 0x02 | ||
6 | #define XT_DCCP_TYPE 0x04 | ||
7 | #define XT_DCCP_OPTION 0x08 | ||
8 | |||
9 | #define XT_DCCP_VALID_FLAGS 0x0f | ||
10 | |||
11 | struct xt_dccp_info { | ||
12 | u_int16_t dpts[2]; /* Min, Max */ | ||
13 | u_int16_t spts[2]; /* Min, Max */ | ||
14 | |||
15 | u_int16_t flags; | ||
16 | u_int16_t invflags; | ||
17 | |||
18 | u_int16_t typemask; | ||
19 | u_int8_t option; | ||
20 | }; | ||
21 | |||
22 | #endif /* _XT_DCCP_H_ */ | ||
23 | |||
diff --git a/include/linux/netfilter/xt_helper.h b/include/linux/netfilter/xt_helper.h new file mode 100644 index 000000000000..6b42763f999d --- /dev/null +++ b/include/linux/netfilter/xt_helper.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _XT_HELPER_H | ||
2 | #define _XT_HELPER_H | ||
3 | |||
4 | struct xt_helper_info { | ||
5 | int invert; | ||
6 | char name[30]; | ||
7 | }; | ||
8 | #endif /* _XT_HELPER_H */ | ||
diff --git a/include/linux/netfilter/xt_length.h b/include/linux/netfilter/xt_length.h new file mode 100644 index 000000000000..7c2b439f73fe --- /dev/null +++ b/include/linux/netfilter/xt_length.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef _XT_LENGTH_H | ||
2 | #define _XT_LENGTH_H | ||
3 | |||
4 | struct xt_length_info { | ||
5 | u_int16_t min, max; | ||
6 | u_int8_t invert; | ||
7 | }; | ||
8 | |||
9 | #endif /*_XT_LENGTH_H*/ | ||
diff --git a/include/linux/netfilter/xt_limit.h b/include/linux/netfilter/xt_limit.h new file mode 100644 index 000000000000..b3ce65375ecb --- /dev/null +++ b/include/linux/netfilter/xt_limit.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #ifndef _XT_RATE_H | ||
2 | #define _XT_RATE_H | ||
3 | |||
4 | /* timings are in milliseconds. */ | ||
5 | #define XT_LIMIT_SCALE 10000 | ||
6 | |||
7 | /* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 | ||
8 | seconds, or one every 59 hours. */ | ||
9 | struct xt_rateinfo { | ||
10 | u_int32_t avg; /* Average secs between packets * scale */ | ||
11 | u_int32_t burst; /* Period multiplier for upper limit. */ | ||
12 | |||
13 | /* Used internally by the kernel */ | ||
14 | unsigned long prev; | ||
15 | u_int32_t credit; | ||
16 | u_int32_t credit_cap, cost; | ||
17 | |||
18 | /* Ugly, ugly fucker. */ | ||
19 | struct xt_rateinfo *master; | ||
20 | }; | ||
21 | #endif /*_XT_RATE_H*/ | ||
diff --git a/include/linux/netfilter/xt_mac.h b/include/linux/netfilter/xt_mac.h new file mode 100644 index 000000000000..b892cdc67e06 --- /dev/null +++ b/include/linux/netfilter/xt_mac.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _XT_MAC_H | ||
2 | #define _XT_MAC_H | ||
3 | |||
4 | struct xt_mac_info { | ||
5 | unsigned char srcaddr[ETH_ALEN]; | ||
6 | int invert; | ||
7 | }; | ||
8 | #endif /*_XT_MAC_H*/ | ||
diff --git a/include/linux/netfilter/xt_mark.h b/include/linux/netfilter/xt_mark.h new file mode 100644 index 000000000000..802dd4842caf --- /dev/null +++ b/include/linux/netfilter/xt_mark.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef _XT_MARK_H | ||
2 | #define _XT_MARK_H | ||
3 | |||
4 | struct xt_mark_info { | ||
5 | unsigned long mark, mask; | ||
6 | u_int8_t invert; | ||
7 | }; | ||
8 | |||
9 | #endif /*_XT_MARK_H*/ | ||
diff --git a/include/linux/netfilter/xt_physdev.h b/include/linux/netfilter/xt_physdev.h new file mode 100644 index 000000000000..25a7a1815b5b --- /dev/null +++ b/include/linux/netfilter/xt_physdev.h | |||
@@ -0,0 +1,24 @@ | |||
1 | #ifndef _XT_PHYSDEV_H | ||
2 | #define _XT_PHYSDEV_H | ||
3 | |||
4 | #ifdef __KERNEL__ | ||
5 | #include <linux/if.h> | ||
6 | #endif | ||
7 | |||
8 | #define XT_PHYSDEV_OP_IN 0x01 | ||
9 | #define XT_PHYSDEV_OP_OUT 0x02 | ||
10 | #define XT_PHYSDEV_OP_BRIDGED 0x04 | ||
11 | #define XT_PHYSDEV_OP_ISIN 0x08 | ||
12 | #define XT_PHYSDEV_OP_ISOUT 0x10 | ||
13 | #define XT_PHYSDEV_OP_MASK (0x20 - 1) | ||
14 | |||
15 | struct xt_physdev_info { | ||
16 | char physindev[IFNAMSIZ]; | ||
17 | char in_mask[IFNAMSIZ]; | ||
18 | char physoutdev[IFNAMSIZ]; | ||
19 | char out_mask[IFNAMSIZ]; | ||
20 | u_int8_t invert; | ||
21 | u_int8_t bitmask; | ||
22 | }; | ||
23 | |||
24 | #endif /*_XT_PHYSDEV_H*/ | ||
diff --git a/include/linux/netfilter/xt_pkttype.h b/include/linux/netfilter/xt_pkttype.h new file mode 100644 index 000000000000..f265cf52faea --- /dev/null +++ b/include/linux/netfilter/xt_pkttype.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _XT_PKTTYPE_H | ||
2 | #define _XT_PKTTYPE_H | ||
3 | |||
4 | struct xt_pkttype_info { | ||
5 | int pkttype; | ||
6 | int invert; | ||
7 | }; | ||
8 | #endif /*_XT_PKTTYPE_H*/ | ||
diff --git a/include/linux/netfilter/xt_realm.h b/include/linux/netfilter/xt_realm.h new file mode 100644 index 000000000000..220e87245716 --- /dev/null +++ b/include/linux/netfilter/xt_realm.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef _XT_REALM_H | ||
2 | #define _XT_REALM_H | ||
3 | |||
4 | struct xt_realm_info { | ||
5 | u_int32_t id; | ||
6 | u_int32_t mask; | ||
7 | u_int8_t invert; | ||
8 | }; | ||
9 | |||
10 | #endif /* _XT_REALM_H */ | ||
diff --git a/include/linux/netfilter/xt_sctp.h b/include/linux/netfilter/xt_sctp.h new file mode 100644 index 000000000000..b157897e7792 --- /dev/null +++ b/include/linux/netfilter/xt_sctp.h | |||
@@ -0,0 +1,107 @@ | |||
1 | #ifndef _XT_SCTP_H_ | ||
2 | #define _XT_SCTP_H_ | ||
3 | |||
4 | #define XT_SCTP_SRC_PORTS 0x01 | ||
5 | #define XT_SCTP_DEST_PORTS 0x02 | ||
6 | #define XT_SCTP_CHUNK_TYPES 0x04 | ||
7 | |||
8 | #define XT_SCTP_VALID_FLAGS 0x07 | ||
9 | |||
10 | #define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0])) | ||
11 | |||
12 | |||
13 | struct xt_sctp_flag_info { | ||
14 | u_int8_t chunktype; | ||
15 | u_int8_t flag; | ||
16 | u_int8_t flag_mask; | ||
17 | }; | ||
18 | |||
19 | #define XT_NUM_SCTP_FLAGS 4 | ||
20 | |||
21 | struct xt_sctp_info { | ||
22 | u_int16_t dpts[2]; /* Min, Max */ | ||
23 | u_int16_t spts[2]; /* Min, Max */ | ||
24 | |||
25 | u_int32_t chunkmap[256 / sizeof (u_int32_t)]; /* Bit mask of chunks to be matched according to RFC 2960 */ | ||
26 | |||
27 | #define SCTP_CHUNK_MATCH_ANY 0x01 /* Match if any of the chunk types are present */ | ||
28 | #define SCTP_CHUNK_MATCH_ALL 0x02 /* Match if all of the chunk types are present */ | ||
29 | #define SCTP_CHUNK_MATCH_ONLY 0x04 /* Match if these are the only chunk types present */ | ||
30 | |||
31 | u_int32_t chunk_match_type; | ||
32 | struct xt_sctp_flag_info flag_info[XT_NUM_SCTP_FLAGS]; | ||
33 | int flag_count; | ||
34 | |||
35 | u_int32_t flags; | ||
36 | u_int32_t invflags; | ||
37 | }; | ||
38 | |||
39 | #define bytes(type) (sizeof(type) * 8) | ||
40 | |||
41 | #define SCTP_CHUNKMAP_SET(chunkmap, type) \ | ||
42 | do { \ | ||
43 | chunkmap[type / bytes(u_int32_t)] |= \ | ||
44 | 1 << (type % bytes(u_int32_t)); \ | ||
45 | } while (0) | ||
46 | |||
47 | #define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \ | ||
48 | do { \ | ||
49 | chunkmap[type / bytes(u_int32_t)] &= \ | ||
50 | ~(1 << (type % bytes(u_int32_t))); \ | ||
51 | } while (0) | ||
52 | |||
53 | #define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \ | ||
54 | ({ \ | ||
55 | (chunkmap[type / bytes (u_int32_t)] & \ | ||
56 | (1 << (type % bytes (u_int32_t)))) ? 1: 0; \ | ||
57 | }) | ||
58 | |||
59 | #define SCTP_CHUNKMAP_RESET(chunkmap) \ | ||
60 | do { \ | ||
61 | int i; \ | ||
62 | for (i = 0; i < ELEMCOUNT(chunkmap); i++) \ | ||
63 | chunkmap[i] = 0; \ | ||
64 | } while (0) | ||
65 | |||
66 | #define SCTP_CHUNKMAP_SET_ALL(chunkmap) \ | ||
67 | do { \ | ||
68 | int i; \ | ||
69 | for (i = 0; i < ELEMCOUNT(chunkmap); i++) \ | ||
70 | chunkmap[i] = ~0; \ | ||
71 | } while (0) | ||
72 | |||
73 | #define SCTP_CHUNKMAP_COPY(destmap, srcmap) \ | ||
74 | do { \ | ||
75 | int i; \ | ||
76 | for (i = 0; i < ELEMCOUNT(chunkmap); i++) \ | ||
77 | destmap[i] = srcmap[i]; \ | ||
78 | } while (0) | ||
79 | |||
80 | #define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \ | ||
81 | ({ \ | ||
82 | int i; \ | ||
83 | int flag = 1; \ | ||
84 | for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \ | ||
85 | if (chunkmap[i]) { \ | ||
86 | flag = 0; \ | ||
87 | break; \ | ||
88 | } \ | ||
89 | } \ | ||
90 | flag; \ | ||
91 | }) | ||
92 | |||
93 | #define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \ | ||
94 | ({ \ | ||
95 | int i; \ | ||
96 | int flag = 1; \ | ||
97 | for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \ | ||
98 | if (chunkmap[i] != ~0) { \ | ||
99 | flag = 0; \ | ||
100 | break; \ | ||
101 | } \ | ||
102 | } \ | ||
103 | flag; \ | ||
104 | }) | ||
105 | |||
106 | #endif /* _XT_SCTP_H_ */ | ||
107 | |||
diff --git a/include/linux/netfilter/xt_state.h b/include/linux/netfilter/xt_state.h new file mode 100644 index 000000000000..c06f32edee07 --- /dev/null +++ b/include/linux/netfilter/xt_state.h | |||
@@ -0,0 +1,13 @@ | |||
1 | #ifndef _XT_STATE_H | ||
2 | #define _XT_STATE_H | ||
3 | |||
4 | #define XT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) | ||
5 | #define XT_STATE_INVALID (1 << 0) | ||
6 | |||
7 | #define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1)) | ||
8 | |||
9 | struct xt_state_info | ||
10 | { | ||
11 | unsigned int statemask; | ||
12 | }; | ||
13 | #endif /*_XT_STATE_H*/ | ||
diff --git a/include/linux/netfilter/xt_string.h b/include/linux/netfilter/xt_string.h new file mode 100644 index 000000000000..3b3419f2637d --- /dev/null +++ b/include/linux/netfilter/xt_string.h | |||
@@ -0,0 +1,18 @@ | |||
1 | #ifndef _XT_STRING_H | ||
2 | #define _XT_STRING_H | ||
3 | |||
4 | #define XT_STRING_MAX_PATTERN_SIZE 128 | ||
5 | #define XT_STRING_MAX_ALGO_NAME_SIZE 16 | ||
6 | |||
7 | struct xt_string_info | ||
8 | { | ||
9 | u_int16_t from_offset; | ||
10 | u_int16_t to_offset; | ||
11 | char algo[XT_STRING_MAX_ALGO_NAME_SIZE]; | ||
12 | char pattern[XT_STRING_MAX_PATTERN_SIZE]; | ||
13 | u_int8_t patlen; | ||
14 | u_int8_t invert; | ||
15 | struct ts_config __attribute__((aligned(8))) *config; | ||
16 | }; | ||
17 | |||
18 | #endif /*_XT_STRING_H*/ | ||
diff --git a/include/linux/netfilter/xt_tcpmss.h b/include/linux/netfilter/xt_tcpmss.h new file mode 100644 index 000000000000..e03274c4c790 --- /dev/null +++ b/include/linux/netfilter/xt_tcpmss.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef _XT_TCPMSS_MATCH_H | ||
2 | #define _XT_TCPMSS_MATCH_H | ||
3 | |||
4 | struct xt_tcpmss_match_info { | ||
5 | u_int16_t mss_min, mss_max; | ||
6 | u_int8_t invert; | ||
7 | }; | ||
8 | |||
9 | #endif /*_XT_TCPMSS_MATCH_H*/ | ||
diff --git a/include/linux/netfilter/xt_tcpudp.h b/include/linux/netfilter/xt_tcpudp.h new file mode 100644 index 000000000000..78bc65f11adf --- /dev/null +++ b/include/linux/netfilter/xt_tcpudp.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef _XT_TCPUDP_H | ||
2 | #define _XT_TCPUDP_H | ||
3 | |||
4 | /* TCP matching stuff */ | ||
5 | struct xt_tcp | ||
6 | { | ||
7 | u_int16_t spts[2]; /* Source port range. */ | ||
8 | u_int16_t dpts[2]; /* Destination port range. */ | ||
9 | u_int8_t option; /* TCP Option iff non-zero*/ | ||
10 | u_int8_t flg_mask; /* TCP flags mask byte */ | ||
11 | u_int8_t flg_cmp; /* TCP flags compare byte */ | ||
12 | u_int8_t invflags; /* Inverse flags */ | ||
13 | }; | ||
14 | |||
15 | /* Values for "inv" field in struct ipt_tcp. */ | ||
16 | #define XT_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ | ||
17 | #define XT_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ | ||
18 | #define XT_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */ | ||
19 | #define XT_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */ | ||
20 | #define XT_TCP_INV_MASK 0x0F /* All possible flags. */ | ||
21 | |||
22 | /* UDP matching stuff */ | ||
23 | struct xt_udp | ||
24 | { | ||
25 | u_int16_t spts[2]; /* Source port range. */ | ||
26 | u_int16_t dpts[2]; /* Destination port range. */ | ||
27 | u_int8_t invflags; /* Inverse flags */ | ||
28 | }; | ||
29 | |||
30 | /* Values for "invflags" field in struct ipt_udp. */ | ||
31 | #define XT_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ | ||
32 | #define XT_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ | ||
33 | #define XT_UDP_INV_MASK 0x03 /* All possible flags. */ | ||
34 | |||
35 | |||
36 | #endif | ||
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index e98a870a20be..fd21796e5131 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h | |||
@@ -19,8 +19,12 @@ | |||
19 | #include <linux/compiler.h> | 19 | #include <linux/compiler.h> |
20 | #include <linux/netfilter_arp.h> | 20 | #include <linux/netfilter_arp.h> |
21 | 21 | ||
22 | #define ARPT_FUNCTION_MAXNAMELEN 30 | 22 | #include <linux/netfilter/x_tables.h> |
23 | #define ARPT_TABLE_MAXNAMELEN 32 | 23 | |
24 | #define ARPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN | ||
25 | #define ARPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN | ||
26 | #define arpt_target xt_target | ||
27 | #define arpt_table xt_table | ||
24 | 28 | ||
25 | #define ARPT_DEV_ADDR_LEN_MAX 16 | 29 | #define ARPT_DEV_ADDR_LEN_MAX 16 |
26 | 30 | ||
@@ -91,11 +95,6 @@ struct arpt_standard_target | |||
91 | int verdict; | 95 | int verdict; |
92 | }; | 96 | }; |
93 | 97 | ||
94 | struct arpt_counters | ||
95 | { | ||
96 | u_int64_t pcnt, bcnt; /* Packet and byte counters */ | ||
97 | }; | ||
98 | |||
99 | /* Values for "flag" field in struct arpt_ip (general arp structure). | 98 | /* Values for "flag" field in struct arpt_ip (general arp structure). |
100 | * No flags defined yet. | 99 | * No flags defined yet. |
101 | */ | 100 | */ |
@@ -130,7 +129,7 @@ struct arpt_entry | |||
130 | unsigned int comefrom; | 129 | unsigned int comefrom; |
131 | 130 | ||
132 | /* Packet and byte counters. */ | 131 | /* Packet and byte counters. */ |
133 | struct arpt_counters counters; | 132 | struct xt_counters counters; |
134 | 133 | ||
135 | /* The matches (if any), then the target. */ | 134 | /* The matches (if any), then the target. */ |
136 | unsigned char elems[0]; | 135 | unsigned char elems[0]; |
@@ -141,23 +140,24 @@ struct arpt_entry | |||
141 | * Unlike BSD Linux inherits IP options so you don't have to use a raw | 140 | * Unlike BSD Linux inherits IP options so you don't have to use a raw |
142 | * socket for this. Instead we check rights in the calls. | 141 | * socket for this. Instead we check rights in the calls. |
143 | */ | 142 | */ |
144 | #define ARPT_BASE_CTL 96 /* base for firewall socket options */ | 143 | #define ARPT_CTL_OFFSET 32 |
144 | #define ARPT_BASE_CTL (XT_BASE_CTL+ARPT_CTL_OFFSET) | ||
145 | 145 | ||
146 | #define ARPT_SO_SET_REPLACE (ARPT_BASE_CTL) | 146 | #define ARPT_SO_SET_REPLACE (XT_SO_SET_REPLACE+ARPT_CTL_OFFSET) |
147 | #define ARPT_SO_SET_ADD_COUNTERS (ARPT_BASE_CTL + 1) | 147 | #define ARPT_SO_SET_ADD_COUNTERS (XT_SO_SET_ADD_COUNTERS+ARPT_CTL_OFFSET) |
148 | #define ARPT_SO_SET_MAX ARPT_SO_SET_ADD_COUNTERS | 148 | #define ARPT_SO_SET_MAX (XT_SO_SET_MAX+ARPT_CTL_OFFSET) |
149 | 149 | ||
150 | #define ARPT_SO_GET_INFO (ARPT_BASE_CTL) | 150 | #define ARPT_SO_GET_INFO (XT_SO_GET_INFO+ARPT_CTL_OFFSET) |
151 | #define ARPT_SO_GET_ENTRIES (ARPT_BASE_CTL + 1) | 151 | #define ARPT_SO_GET_ENTRIES (XT_SO_GET_ENTRIES+ARPT_CTL_OFFSET) |
152 | /* #define ARPT_SO_GET_REVISION_MATCH (ARPT_BASE_CTL + 2)*/ | 152 | /* #define ARPT_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH */ |
153 | #define ARPT_SO_GET_REVISION_TARGET (ARPT_BASE_CTL + 3) | 153 | #define ARPT_SO_GET_REVISION_TARGET (XT_SO_GET_REVISION_TARGET+ARPT_CTL_OFFSET) |
154 | #define ARPT_SO_GET_MAX ARPT_SO_GET_REVISION_TARGET | 154 | #define ARPT_SO_GET_MAX (XT_SO_GET_REVISION_TARGET+ARPT_CTL_OFFSET) |
155 | 155 | ||
156 | /* CONTINUE verdict for targets */ | 156 | /* CONTINUE verdict for targets */ |
157 | #define ARPT_CONTINUE 0xFFFFFFFF | 157 | #define ARPT_CONTINUE XT_CONTINUE |
158 | 158 | ||
159 | /* For standard target */ | 159 | /* For standard target */ |
160 | #define ARPT_RETURN (-NF_REPEAT - 1) | 160 | #define ARPT_RETURN XT_RETURN |
161 | 161 | ||
162 | /* The argument to ARPT_SO_GET_INFO */ | 162 | /* The argument to ARPT_SO_GET_INFO */ |
163 | struct arpt_getinfo | 163 | struct arpt_getinfo |
@@ -208,23 +208,14 @@ struct arpt_replace | |||
208 | /* Number of counters (must be equal to current number of entries). */ | 208 | /* Number of counters (must be equal to current number of entries). */ |
209 | unsigned int num_counters; | 209 | unsigned int num_counters; |
210 | /* The old entries' counters. */ | 210 | /* The old entries' counters. */ |
211 | struct arpt_counters __user *counters; | 211 | struct xt_counters __user *counters; |
212 | 212 | ||
213 | /* The entries (hang off end: not really an array). */ | 213 | /* The entries (hang off end: not really an array). */ |
214 | struct arpt_entry entries[0]; | 214 | struct arpt_entry entries[0]; |
215 | }; | 215 | }; |
216 | 216 | ||
217 | /* The argument to ARPT_SO_ADD_COUNTERS. */ | 217 | /* The argument to ARPT_SO_ADD_COUNTERS. */ |
218 | struct arpt_counters_info | 218 | #define arpt_counters_info xt_counters_info |
219 | { | ||
220 | /* Which table. */ | ||
221 | char name[ARPT_TABLE_MAXNAMELEN]; | ||
222 | |||
223 | unsigned int num_counters; | ||
224 | |||
225 | /* The counters (actually `number' of these). */ | ||
226 | struct arpt_counters counters[0]; | ||
227 | }; | ||
228 | 219 | ||
229 | /* The argument to ARPT_SO_GET_ENTRIES. */ | 220 | /* The argument to ARPT_SO_GET_ENTRIES. */ |
230 | struct arpt_get_entries | 221 | struct arpt_get_entries |
@@ -239,19 +230,10 @@ struct arpt_get_entries | |||
239 | struct arpt_entry entrytable[0]; | 230 | struct arpt_entry entrytable[0]; |
240 | }; | 231 | }; |
241 | 232 | ||
242 | /* The argument to ARPT_SO_GET_REVISION_*. Returns highest revision | ||
243 | * kernel supports, if >= revision. */ | ||
244 | struct arpt_get_revision | ||
245 | { | ||
246 | char name[ARPT_FUNCTION_MAXNAMELEN-1]; | ||
247 | |||
248 | u_int8_t revision; | ||
249 | }; | ||
250 | |||
251 | /* Standard return verdict, or do jump. */ | 233 | /* Standard return verdict, or do jump. */ |
252 | #define ARPT_STANDARD_TARGET "" | 234 | #define ARPT_STANDARD_TARGET XT_STANDARD_TARGET |
253 | /* Error verdict. */ | 235 | /* Error verdict. */ |
254 | #define ARPT_ERROR_TARGET "ERROR" | 236 | #define ARPT_ERROR_TARGET XT_ERROR_TARGET |
255 | 237 | ||
256 | /* Helper functions */ | 238 | /* Helper functions */ |
257 | static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e) | 239 | static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e) |
@@ -281,63 +263,8 @@ static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e | |||
281 | */ | 263 | */ |
282 | #ifdef __KERNEL__ | 264 | #ifdef __KERNEL__ |
283 | 265 | ||
284 | /* Registration hooks for targets. */ | 266 | #define arpt_register_target(tgt) xt_register_target(NF_ARP, tgt) |
285 | struct arpt_target | 267 | #define arpt_unregister_target(tgt) xt_unregister_target(NF_ARP, tgt) |
286 | { | ||
287 | struct list_head list; | ||
288 | |||
289 | const char name[ARPT_FUNCTION_MAXNAMELEN-1]; | ||
290 | |||
291 | u_int8_t revision; | ||
292 | |||
293 | /* Returns verdict. */ | ||
294 | unsigned int (*target)(struct sk_buff **pskb, | ||
295 | unsigned int hooknum, | ||
296 | const struct net_device *in, | ||
297 | const struct net_device *out, | ||
298 | const void *targinfo, | ||
299 | void *userdata); | ||
300 | |||
301 | /* Called when user tries to insert an entry of this type: | ||
302 | hook_mask is a bitmask of hooks from which it can be | ||
303 | called. */ | ||
304 | /* Should return true or false. */ | ||
305 | int (*checkentry)(const char *tablename, | ||
306 | const struct arpt_entry *e, | ||
307 | void *targinfo, | ||
308 | unsigned int targinfosize, | ||
309 | unsigned int hook_mask); | ||
310 | |||
311 | /* Called when entry of this type deleted. */ | ||
312 | void (*destroy)(void *targinfo, unsigned int targinfosize); | ||
313 | |||
314 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
315 | struct module *me; | ||
316 | }; | ||
317 | |||
318 | extern int arpt_register_target(struct arpt_target *target); | ||
319 | extern void arpt_unregister_target(struct arpt_target *target); | ||
320 | |||
321 | /* Furniture shopping... */ | ||
322 | struct arpt_table | ||
323 | { | ||
324 | struct list_head list; | ||
325 | |||
326 | /* A unique name... */ | ||
327 | char name[ARPT_TABLE_MAXNAMELEN]; | ||
328 | |||
329 | /* What hooks you will enter on */ | ||
330 | unsigned int valid_hooks; | ||
331 | |||
332 | /* Lock for the curtain */ | ||
333 | rwlock_t lock; | ||
334 | |||
335 | /* Man behind the curtain... */ | ||
336 | struct arpt_table_info *private; | ||
337 | |||
338 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
339 | struct module *me; | ||
340 | }; | ||
341 | 268 | ||
342 | extern int arpt_register_table(struct arpt_table *table, | 269 | extern int arpt_register_table(struct arpt_table *table, |
343 | const struct arpt_replace *repl); | 270 | const struct arpt_replace *repl); |
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index b3432ab59a17..215765f043e6 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h | |||
@@ -199,9 +199,6 @@ ip_conntrack_put(struct ip_conntrack *ct) | |||
199 | nf_conntrack_put(&ct->ct_general); | 199 | nf_conntrack_put(&ct->ct_general); |
200 | } | 200 | } |
201 | 201 | ||
202 | /* call to create an explicit dependency on ip_conntrack. */ | ||
203 | extern void need_ip_conntrack(void); | ||
204 | |||
205 | extern int invert_tuplepr(struct ip_conntrack_tuple *inverse, | 202 | extern int invert_tuplepr(struct ip_conntrack_tuple *inverse, |
206 | const struct ip_conntrack_tuple *orig); | 203 | const struct ip_conntrack_tuple *orig); |
207 | 204 | ||
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index d19d65cf4530..76ba24b68515 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h | |||
@@ -25,8 +25,14 @@ | |||
25 | #include <linux/compiler.h> | 25 | #include <linux/compiler.h> |
26 | #include <linux/netfilter_ipv4.h> | 26 | #include <linux/netfilter_ipv4.h> |
27 | 27 | ||
28 | #define IPT_FUNCTION_MAXNAMELEN 30 | 28 | #include <linux/netfilter/x_tables.h> |
29 | #define IPT_TABLE_MAXNAMELEN 32 | 29 | |
30 | #define IPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN | ||
31 | #define IPT_TABLE_MAXNAMELEN XT_FUNCTION_MAXNAMELEN | ||
32 | #define ipt_match xt_match | ||
33 | #define ipt_target xt_target | ||
34 | #define ipt_table xt_table | ||
35 | #define ipt_get_revision xt_get_revision | ||
30 | 36 | ||
31 | /* Yes, Virginia, you have to zero the padding. */ | 37 | /* Yes, Virginia, you have to zero the padding. */ |
32 | struct ipt_ip { | 38 | struct ipt_ip { |
@@ -102,10 +108,7 @@ struct ipt_standard_target | |||
102 | int verdict; | 108 | int verdict; |
103 | }; | 109 | }; |
104 | 110 | ||
105 | struct ipt_counters | 111 | #define ipt_counters xt_counters |
106 | { | ||
107 | u_int64_t pcnt, bcnt; /* Packet and byte counters */ | ||
108 | }; | ||
109 | 112 | ||
110 | /* Values for "flag" field in struct ipt_ip (general ip structure). */ | 113 | /* Values for "flag" field in struct ipt_ip (general ip structure). */ |
111 | #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ | 114 | #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ |
@@ -119,7 +122,7 @@ struct ipt_counters | |||
119 | #define IPT_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ | 122 | #define IPT_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ |
120 | #define IPT_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ | 123 | #define IPT_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ |
121 | #define IPT_INV_FRAG 0x20 /* Invert the sense of FRAG. */ | 124 | #define IPT_INV_FRAG 0x20 /* Invert the sense of FRAG. */ |
122 | #define IPT_INV_PROTO 0x40 /* Invert the sense of PROTO. */ | 125 | #define IPT_INV_PROTO XT_INV_PROTO |
123 | #define IPT_INV_MASK 0x7F /* All possible flag bits mask. */ | 126 | #define IPT_INV_MASK 0x7F /* All possible flag bits mask. */ |
124 | 127 | ||
125 | /* This structure defines each of the firewall rules. Consists of 3 | 128 | /* This structure defines each of the firewall rules. Consists of 3 |
@@ -141,7 +144,7 @@ struct ipt_entry | |||
141 | unsigned int comefrom; | 144 | unsigned int comefrom; |
142 | 145 | ||
143 | /* Packet and byte counters. */ | 146 | /* Packet and byte counters. */ |
144 | struct ipt_counters counters; | 147 | struct xt_counters counters; |
145 | 148 | ||
146 | /* The matches (if any), then the target. */ | 149 | /* The matches (if any), then the target. */ |
147 | unsigned char elems[0]; | 150 | unsigned char elems[0]; |
@@ -151,54 +154,34 @@ struct ipt_entry | |||
151 | * New IP firewall options for [gs]etsockopt at the RAW IP level. | 154 | * New IP firewall options for [gs]etsockopt at the RAW IP level. |
152 | * Unlike BSD Linux inherits IP options so you don't have to use a raw | 155 | * Unlike BSD Linux inherits IP options so you don't have to use a raw |
153 | * socket for this. Instead we check rights in the calls. */ | 156 | * socket for this. Instead we check rights in the calls. */ |
154 | #define IPT_BASE_CTL 64 /* base for firewall socket options */ | 157 | #define IPT_BASE_CTL XT_BASE_CTL |
155 | 158 | ||
156 | #define IPT_SO_SET_REPLACE (IPT_BASE_CTL) | 159 | #define IPT_SO_SET_REPLACE XT_SO_SET_REPLACE |
157 | #define IPT_SO_SET_ADD_COUNTERS (IPT_BASE_CTL + 1) | 160 | #define IPT_SO_SET_ADD_COUNTERS XT_SO_SET_ADD_COUNTERS |
158 | #define IPT_SO_SET_MAX IPT_SO_SET_ADD_COUNTERS | 161 | #define IPT_SO_SET_MAX XT_SO_SET_MAX |
159 | 162 | ||
160 | #define IPT_SO_GET_INFO (IPT_BASE_CTL) | 163 | #define IPT_SO_GET_INFO XT_SO_GET_INFO |
161 | #define IPT_SO_GET_ENTRIES (IPT_BASE_CTL + 1) | 164 | #define IPT_SO_GET_ENTRIES XT_SO_GET_ENTRIES |
162 | #define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2) | 165 | #define IPT_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH |
163 | #define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3) | 166 | #define IPT_SO_GET_REVISION_TARGET XT_SO_GET_REVISION_TARGET |
164 | #define IPT_SO_GET_MAX IPT_SO_GET_REVISION_TARGET | 167 | #define IPT_SO_GET_MAX XT_SO_GET_REVISION_TARGET |
165 | 168 | ||
166 | /* CONTINUE verdict for targets */ | 169 | #define IPT_CONTINUE XT_CONTINUE |
167 | #define IPT_CONTINUE 0xFFFFFFFF | 170 | #define IPT_RETURN XT_RETURN |
168 | 171 | ||
169 | /* For standard target */ | 172 | #include <linux/netfilter/xt_tcpudp.h> |
170 | #define IPT_RETURN (-NF_REPEAT - 1) | 173 | #define ipt_udp xt_udp |
174 | #define ipt_tcp xt_tcp | ||
171 | 175 | ||
172 | /* TCP matching stuff */ | 176 | #define IPT_TCP_INV_SRCPT XT_TCP_INV_SRCPT |
173 | struct ipt_tcp | 177 | #define IPT_TCP_INV_DSTPT XT_TCP_INV_DSTPT |
174 | { | 178 | #define IPT_TCP_INV_FLAGS XT_TCP_INV_FLAGS |
175 | u_int16_t spts[2]; /* Source port range. */ | 179 | #define IPT_TCP_INV_OPTION XT_TCP_INV_OPTION |
176 | u_int16_t dpts[2]; /* Destination port range. */ | 180 | #define IPT_TCP_INV_MASK XT_TCP_INV_MASK |
177 | u_int8_t option; /* TCP Option iff non-zero*/ | ||
178 | u_int8_t flg_mask; /* TCP flags mask byte */ | ||
179 | u_int8_t flg_cmp; /* TCP flags compare byte */ | ||
180 | u_int8_t invflags; /* Inverse flags */ | ||
181 | }; | ||
182 | |||
183 | /* Values for "inv" field in struct ipt_tcp. */ | ||
184 | #define IPT_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ | ||
185 | #define IPT_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ | ||
186 | #define IPT_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */ | ||
187 | #define IPT_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */ | ||
188 | #define IPT_TCP_INV_MASK 0x0F /* All possible flags. */ | ||
189 | |||
190 | /* UDP matching stuff */ | ||
191 | struct ipt_udp | ||
192 | { | ||
193 | u_int16_t spts[2]; /* Source port range. */ | ||
194 | u_int16_t dpts[2]; /* Destination port range. */ | ||
195 | u_int8_t invflags; /* Inverse flags */ | ||
196 | }; | ||
197 | 181 | ||
198 | /* Values for "invflags" field in struct ipt_udp. */ | 182 | #define IPT_UDP_INV_SRCPT XT_UDP_INV_SRCPT |
199 | #define IPT_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ | 183 | #define IPT_UDP_INV_DSTPT XT_UDP_INV_DSTPT |
200 | #define IPT_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ | 184 | #define IPT_UDP_INV_MASK XT_UDP_INV_MASK |
201 | #define IPT_UDP_INV_MASK 0x03 /* All possible flags. */ | ||
202 | 185 | ||
203 | /* ICMP matching stuff */ | 186 | /* ICMP matching stuff */ |
204 | struct ipt_icmp | 187 | struct ipt_icmp |
@@ -260,23 +243,14 @@ struct ipt_replace | |||
260 | /* Number of counters (must be equal to current number of entries). */ | 243 | /* Number of counters (must be equal to current number of entries). */ |
261 | unsigned int num_counters; | 244 | unsigned int num_counters; |
262 | /* The old entries' counters. */ | 245 | /* The old entries' counters. */ |
263 | struct ipt_counters __user *counters; | 246 | struct xt_counters __user *counters; |
264 | 247 | ||
265 | /* The entries (hang off end: not really an array). */ | 248 | /* The entries (hang off end: not really an array). */ |
266 | struct ipt_entry entries[0]; | 249 | struct ipt_entry entries[0]; |
267 | }; | 250 | }; |
268 | 251 | ||
269 | /* The argument to IPT_SO_ADD_COUNTERS. */ | 252 | /* The argument to IPT_SO_ADD_COUNTERS. */ |
270 | struct ipt_counters_info | 253 | #define ipt_counters_info xt_counters_info |
271 | { | ||
272 | /* Which table. */ | ||
273 | char name[IPT_TABLE_MAXNAMELEN]; | ||
274 | |||
275 | unsigned int num_counters; | ||
276 | |||
277 | /* The counters (actually `number' of these). */ | ||
278 | struct ipt_counters counters[0]; | ||
279 | }; | ||
280 | 254 | ||
281 | /* The argument to IPT_SO_GET_ENTRIES. */ | 255 | /* The argument to IPT_SO_GET_ENTRIES. */ |
282 | struct ipt_get_entries | 256 | struct ipt_get_entries |
@@ -291,19 +265,10 @@ struct ipt_get_entries | |||
291 | struct ipt_entry entrytable[0]; | 265 | struct ipt_entry entrytable[0]; |
292 | }; | 266 | }; |
293 | 267 | ||
294 | /* The argument to IPT_SO_GET_REVISION_*. Returns highest revision | ||
295 | * kernel supports, if >= revision. */ | ||
296 | struct ipt_get_revision | ||
297 | { | ||
298 | char name[IPT_FUNCTION_MAXNAMELEN-1]; | ||
299 | |||
300 | u_int8_t revision; | ||
301 | }; | ||
302 | |||
303 | /* Standard return verdict, or do jump. */ | 268 | /* Standard return verdict, or do jump. */ |
304 | #define IPT_STANDARD_TARGET "" | 269 | #define IPT_STANDARD_TARGET XT_STANDARD_TARGET |
305 | /* Error verdict. */ | 270 | /* Error verdict. */ |
306 | #define IPT_ERROR_TARGET "ERROR" | 271 | #define IPT_ERROR_TARGET XT_ERROR_TARGET |
307 | 272 | ||
308 | /* Helper functions */ | 273 | /* Helper functions */ |
309 | static __inline__ struct ipt_entry_target * | 274 | static __inline__ struct ipt_entry_target * |
@@ -356,103 +321,18 @@ ipt_get_target(struct ipt_entry *e) | |||
356 | #include <linux/init.h> | 321 | #include <linux/init.h> |
357 | extern void ipt_init(void) __init; | 322 | extern void ipt_init(void) __init; |
358 | 323 | ||
359 | struct ipt_match | 324 | #define ipt_register_target(tgt) xt_register_target(AF_INET, tgt) |
360 | { | 325 | #define ipt_unregister_target(tgt) xt_unregister_target(AF_INET, tgt) |
361 | struct list_head list; | ||
362 | |||
363 | const char name[IPT_FUNCTION_MAXNAMELEN-1]; | ||
364 | |||
365 | u_int8_t revision; | ||
366 | |||
367 | /* Return true or false: return FALSE and set *hotdrop = 1 to | ||
368 | force immediate packet drop. */ | ||
369 | /* Arguments changed since 2.4, as this must now handle | ||
370 | non-linear skbs, using skb_copy_bits and | ||
371 | skb_ip_make_writable. */ | ||
372 | int (*match)(const struct sk_buff *skb, | ||
373 | const struct net_device *in, | ||
374 | const struct net_device *out, | ||
375 | const void *matchinfo, | ||
376 | int offset, | ||
377 | int *hotdrop); | ||
378 | |||
379 | /* Called when user tries to insert an entry of this type. */ | ||
380 | /* Should return true or false. */ | ||
381 | int (*checkentry)(const char *tablename, | ||
382 | const struct ipt_ip *ip, | ||
383 | void *matchinfo, | ||
384 | unsigned int matchinfosize, | ||
385 | unsigned int hook_mask); | ||
386 | |||
387 | /* Called when entry of this type deleted. */ | ||
388 | void (*destroy)(void *matchinfo, unsigned int matchinfosize); | ||
389 | |||
390 | /* Set this to THIS_MODULE. */ | ||
391 | struct module *me; | ||
392 | }; | ||
393 | |||
394 | /* Registration hooks for targets. */ | ||
395 | struct ipt_target | ||
396 | { | ||
397 | struct list_head list; | ||
398 | |||
399 | const char name[IPT_FUNCTION_MAXNAMELEN-1]; | ||
400 | |||
401 | u_int8_t revision; | ||
402 | |||
403 | /* Called when user tries to insert an entry of this type: | ||
404 | hook_mask is a bitmask of hooks from which it can be | ||
405 | called. */ | ||
406 | /* Should return true or false. */ | ||
407 | int (*checkentry)(const char *tablename, | ||
408 | const struct ipt_entry *e, | ||
409 | void *targinfo, | ||
410 | unsigned int targinfosize, | ||
411 | unsigned int hook_mask); | ||
412 | |||
413 | /* Called when entry of this type deleted. */ | ||
414 | void (*destroy)(void *targinfo, unsigned int targinfosize); | ||
415 | |||
416 | /* Returns verdict. Argument order changed since 2.4, as this | ||
417 | must now handle non-linear skbs, using skb_copy_bits and | ||
418 | skb_ip_make_writable. */ | ||
419 | unsigned int (*target)(struct sk_buff **pskb, | ||
420 | const struct net_device *in, | ||
421 | const struct net_device *out, | ||
422 | unsigned int hooknum, | ||
423 | const void *targinfo, | ||
424 | void *userdata); | ||
425 | |||
426 | /* Set this to THIS_MODULE. */ | ||
427 | struct module *me; | ||
428 | }; | ||
429 | 326 | ||
430 | extern int ipt_register_target(struct ipt_target *target); | 327 | #define ipt_register_match(mtch) xt_register_match(AF_INET, mtch) |
431 | extern void ipt_unregister_target(struct ipt_target *target); | 328 | #define ipt_unregister_match(mtch) xt_unregister_match(AF_INET, mtch) |
432 | 329 | ||
433 | extern int ipt_register_match(struct ipt_match *match); | 330 | //#define ipt_register_table(tbl, repl) xt_register_table(AF_INET, tbl, repl) |
434 | extern void ipt_unregister_match(struct ipt_match *match); | 331 | //#define ipt_unregister_table(tbl) xt_unregister_table(AF_INET, tbl) |
435 | 332 | ||
436 | /* Furniture shopping... */ | 333 | extern int ipt_register_table(struct ipt_table *table, |
437 | struct ipt_table | 334 | const struct ipt_replace *repl); |
438 | { | 335 | extern void ipt_unregister_table(struct ipt_table *table); |
439 | struct list_head list; | ||
440 | |||
441 | /* A unique name... */ | ||
442 | char name[IPT_TABLE_MAXNAMELEN]; | ||
443 | |||
444 | /* What hooks you will enter on */ | ||
445 | unsigned int valid_hooks; | ||
446 | |||
447 | /* Lock for the curtain */ | ||
448 | rwlock_t lock; | ||
449 | |||
450 | /* Man behind the curtain... */ | ||
451 | struct ipt_table_info *private; | ||
452 | |||
453 | /* Set to THIS_MODULE. */ | ||
454 | struct module *me; | ||
455 | }; | ||
456 | 336 | ||
457 | /* net/sched/ipt.c: Gimme access to your targets! Gets target->me. */ | 337 | /* net/sched/ipt.c: Gimme access to your targets! Gets target->me. */ |
458 | extern struct ipt_target *ipt_find_target(const char *name, u8 revision); | 338 | extern struct ipt_target *ipt_find_target(const char *name, u8 revision); |
@@ -476,9 +356,6 @@ struct ipt_error | |||
476 | struct ipt_error_target target; | 356 | struct ipt_error_target target; |
477 | }; | 357 | }; |
478 | 358 | ||
479 | extern int ipt_register_table(struct ipt_table *table, | ||
480 | const struct ipt_replace *repl); | ||
481 | extern void ipt_unregister_table(struct ipt_table *table); | ||
482 | extern unsigned int ipt_do_table(struct sk_buff **pskb, | 359 | extern unsigned int ipt_do_table(struct sk_buff **pskb, |
483 | unsigned int hook, | 360 | unsigned int hook, |
484 | const struct net_device *in, | 361 | const struct net_device *in, |
@@ -486,6 +363,6 @@ extern unsigned int ipt_do_table(struct sk_buff **pskb, | |||
486 | struct ipt_table *table, | 363 | struct ipt_table *table, |
487 | void *userdata); | 364 | void *userdata); |
488 | 365 | ||
489 | #define IPT_ALIGN(s) (((s) + (__alignof__(struct ipt_entry)-1)) & ~(__alignof__(struct ipt_entry)-1)) | 366 | #define IPT_ALIGN(s) XT_ALIGN(s) |
490 | #endif /*__KERNEL__*/ | 367 | #endif /*__KERNEL__*/ |
491 | #endif /* _IPTABLES_H */ | 368 | #endif /* _IPTABLES_H */ |
diff --git a/include/linux/netfilter_ipv4/ipt_CLASSIFY.h b/include/linux/netfilter_ipv4/ipt_CLASSIFY.h index 7596e3dd00ca..a46d511b5c36 100644 --- a/include/linux/netfilter_ipv4/ipt_CLASSIFY.h +++ b/include/linux/netfilter_ipv4/ipt_CLASSIFY.h | |||
@@ -1,8 +1,7 @@ | |||
1 | #ifndef _IPT_CLASSIFY_H | 1 | #ifndef _IPT_CLASSIFY_H |
2 | #define _IPT_CLASSIFY_H | 2 | #define _IPT_CLASSIFY_H |
3 | 3 | ||
4 | struct ipt_classify_target_info { | 4 | #include <linux/netfilter/xt_CLASSIFY.h> |
5 | u_int32_t priority; | 5 | #define ipt_classify_target_info xt_classify_target_info |
6 | }; | ||
7 | 6 | ||
8 | #endif /*_IPT_CLASSIFY_H */ | 7 | #endif /*_IPT_CLASSIFY_H */ |
diff --git a/include/linux/netfilter_ipv4/ipt_CONNMARK.h b/include/linux/netfilter_ipv4/ipt_CONNMARK.h index d3c02536fc4c..9ecfee0a9e33 100644 --- a/include/linux/netfilter_ipv4/ipt_CONNMARK.h +++ b/include/linux/netfilter_ipv4/ipt_CONNMARK.h | |||
@@ -9,17 +9,11 @@ | |||
9 | * the Free Software Foundation; either version 2 of the License, or | 9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. | 10 | * (at your option) any later version. |
11 | */ | 11 | */ |
12 | #include <linux/netfilter/xt_CONNMARK.h> | ||
13 | #define IPT_CONNMARK_SET XT_CONNMARK_SET | ||
14 | #define IPT_CONNMARK_SAVE XT_CONNMARK_SAVE | ||
15 | #define IPT_CONNMARK_RESTORE XT_CONNMARK_RESTORE | ||
12 | 16 | ||
13 | enum { | 17 | #define ipt_connmark_target_info xt_connmark_target_info |
14 | IPT_CONNMARK_SET = 0, | ||
15 | IPT_CONNMARK_SAVE, | ||
16 | IPT_CONNMARK_RESTORE | ||
17 | }; | ||
18 | |||
19 | struct ipt_connmark_target_info { | ||
20 | unsigned long mark; | ||
21 | unsigned long mask; | ||
22 | u_int8_t mode; | ||
23 | }; | ||
24 | 18 | ||
25 | #endif /*_IPT_CONNMARK_H_target*/ | 19 | #endif /*_IPT_CONNMARK_H_target*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_MARK.h b/include/linux/netfilter_ipv4/ipt_MARK.h index f47485790ed4..697a486a96d3 100644 --- a/include/linux/netfilter_ipv4/ipt_MARK.h +++ b/include/linux/netfilter_ipv4/ipt_MARK.h | |||
@@ -1,20 +1,18 @@ | |||
1 | #ifndef _IPT_MARK_H_target | 1 | #ifndef _IPT_MARK_H_target |
2 | #define _IPT_MARK_H_target | 2 | #define _IPT_MARK_H_target |
3 | 3 | ||
4 | /* Backwards compatibility for old userspace */ | ||
5 | |||
6 | #include <linux/netfilter/xt_MARK.h> | ||
7 | |||
4 | /* Version 0 */ | 8 | /* Version 0 */ |
5 | struct ipt_mark_target_info { | 9 | #define ipt_mark_target_info xt_mark_target_info |
6 | unsigned long mark; | ||
7 | }; | ||
8 | 10 | ||
9 | /* Version 1 */ | 11 | /* Version 1 */ |
10 | enum { | 12 | #define IPT_MARK_SET XT_MARK_SET |
11 | IPT_MARK_SET=0, | 13 | #define IPT_MARK_AND XT_MARK_AND |
12 | IPT_MARK_AND, | 14 | #define IPT_MARK_OR XT_MARK_OR |
13 | IPT_MARK_OR | 15 | |
14 | }; | 16 | #define ipt_mark_target_info_v1 xt_mark_target_info_v1 |
15 | 17 | ||
16 | struct ipt_mark_target_info_v1 { | ||
17 | unsigned long mark; | ||
18 | u_int8_t mode; | ||
19 | }; | ||
20 | #endif /*_IPT_MARK_H_target*/ | 18 | #endif /*_IPT_MARK_H_target*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_NFQUEUE.h b/include/linux/netfilter_ipv4/ipt_NFQUEUE.h index b5b2943b0c66..97a2a7557cb9 100644 --- a/include/linux/netfilter_ipv4/ipt_NFQUEUE.h +++ b/include/linux/netfilter_ipv4/ipt_NFQUEUE.h | |||
@@ -8,9 +8,9 @@ | |||
8 | #ifndef _IPT_NFQ_TARGET_H | 8 | #ifndef _IPT_NFQ_TARGET_H |
9 | #define _IPT_NFQ_TARGET_H | 9 | #define _IPT_NFQ_TARGET_H |
10 | 10 | ||
11 | /* target info */ | 11 | /* Backwards compatibility for old userspace */ |
12 | struct ipt_NFQ_info { | 12 | #include <linux/netfilter/xt_NFQUEUE.h> |
13 | u_int16_t queuenum; | 13 | |
14 | }; | 14 | #define ipt_NFQ_info xt_NFQ_info |
15 | 15 | ||
16 | #endif /* _IPT_DSCP_TARGET_H */ | 16 | #endif /* _IPT_DSCP_TARGET_H */ |
diff --git a/include/linux/netfilter_ipv4/ipt_comment.h b/include/linux/netfilter_ipv4/ipt_comment.h index 85c1123c29ce..ae2afc2f7481 100644 --- a/include/linux/netfilter_ipv4/ipt_comment.h +++ b/include/linux/netfilter_ipv4/ipt_comment.h | |||
@@ -1,10 +1,10 @@ | |||
1 | #ifndef _IPT_COMMENT_H | 1 | #ifndef _IPT_COMMENT_H |
2 | #define _IPT_COMMENT_H | 2 | #define _IPT_COMMENT_H |
3 | 3 | ||
4 | #define IPT_MAX_COMMENT_LEN 256 | 4 | #include <linux/netfilter/xt_comment.h> |
5 | 5 | ||
6 | struct ipt_comment_info { | 6 | #define IPT_MAX_COMMENT_LEN XT_MAX_COMMENT_LEN |
7 | unsigned char comment[IPT_MAX_COMMENT_LEN]; | 7 | |
8 | }; | 8 | #define ipt_comment_info xt_comment_info |
9 | 9 | ||
10 | #endif /* _IPT_COMMENT_H */ | 10 | #endif /* _IPT_COMMENT_H */ |
diff --git a/include/linux/netfilter_ipv4/ipt_connbytes.h b/include/linux/netfilter_ipv4/ipt_connbytes.h index 9e5532f8d8ac..b04dfa3083c9 100644 --- a/include/linux/netfilter_ipv4/ipt_connbytes.h +++ b/include/linux/netfilter_ipv4/ipt_connbytes.h | |||
@@ -1,25 +1,18 @@ | |||
1 | #ifndef _IPT_CONNBYTES_H | 1 | #ifndef _IPT_CONNBYTES_H |
2 | #define _IPT_CONNBYTES_H | 2 | #define _IPT_CONNBYTES_H |
3 | 3 | ||
4 | enum ipt_connbytes_what { | 4 | #include <net/netfilter/xt_connbytes.h> |
5 | IPT_CONNBYTES_PKTS, | 5 | #define ipt_connbytes_what xt_connbytes_what |
6 | IPT_CONNBYTES_BYTES, | ||
7 | IPT_CONNBYTES_AVGPKT, | ||
8 | }; | ||
9 | 6 | ||
10 | enum ipt_connbytes_direction { | 7 | #define IPT_CONNBYTES_PKTS XT_CONNBYTES_PACKETS |
11 | IPT_CONNBYTES_DIR_ORIGINAL, | 8 | #define IPT_CONNBYTES_BYTES XT_CONNBYTES_BYTES |
12 | IPT_CONNBYTES_DIR_REPLY, | 9 | #define IPT_CONNBYTES_AVGPKT XT_CONNBYTES_AVGPKT |
13 | IPT_CONNBYTES_DIR_BOTH, | 10 | |
14 | }; | 11 | #define ipt_connbytes_direction xt_connbytes_direction |
12 | #define IPT_CONNBYTES_DIR_ORIGINAL XT_CONNBYTES_DIR_ORIGINAL | ||
13 | #define IPT_CONNBYTES_DIR_REPLY XT_CONNBYTES_DIR_REPLY | ||
14 | #define IPT_CONNBYTES_DIR_BOTH XT_CONNBYTES_DIR_BOTH | ||
15 | |||
16 | #define ipt_connbytes_info xt_connbytes_info | ||
15 | 17 | ||
16 | struct ipt_connbytes_info | ||
17 | { | ||
18 | struct { | ||
19 | aligned_u64 from; /* count to be matched */ | ||
20 | aligned_u64 to; /* count to be matched */ | ||
21 | } count; | ||
22 | u_int8_t what; /* ipt_connbytes_what */ | ||
23 | u_int8_t direction; /* ipt_connbytes_direction */ | ||
24 | }; | ||
25 | #endif | 18 | #endif |
diff --git a/include/linux/netfilter_ipv4/ipt_connmark.h b/include/linux/netfilter_ipv4/ipt_connmark.h index 46573270d9aa..c7ba6560d44c 100644 --- a/include/linux/netfilter_ipv4/ipt_connmark.h +++ b/include/linux/netfilter_ipv4/ipt_connmark.h | |||
@@ -1,18 +1,7 @@ | |||
1 | #ifndef _IPT_CONNMARK_H | 1 | #ifndef _IPT_CONNMARK_H |
2 | #define _IPT_CONNMARK_H | 2 | #define _IPT_CONNMARK_H |
3 | 3 | ||
4 | /* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> | 4 | #include <linux/netfilter/xt_connmark.h> |
5 | * by Henrik Nordstrom <hno@marasystems.com> | 5 | #define ipt_connmark_info xt_connmark_info |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | struct ipt_connmark_info { | ||
14 | unsigned long mark, mask; | ||
15 | u_int8_t invert; | ||
16 | }; | ||
17 | 6 | ||
18 | #endif /*_IPT_CONNMARK_H*/ | 7 | #endif /*_IPT_CONNMARK_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_conntrack.h b/include/linux/netfilter_ipv4/ipt_conntrack.h index 413c5658bd3a..cde6762949c5 100644 --- a/include/linux/netfilter_ipv4/ipt_conntrack.h +++ b/include/linux/netfilter_ipv4/ipt_conntrack.h | |||
@@ -5,56 +5,24 @@ | |||
5 | #ifndef _IPT_CONNTRACK_H | 5 | #ifndef _IPT_CONNTRACK_H |
6 | #define _IPT_CONNTRACK_H | 6 | #define _IPT_CONNTRACK_H |
7 | 7 | ||
8 | #define IPT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) | 8 | #include <linux/netfilter/xt_conntrack.h> |
9 | #define IPT_CONNTRACK_STATE_INVALID (1 << 0) | ||
10 | 9 | ||
11 | #define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1)) | 10 | #define IPT_CONNTRACK_STATE_BIT(ctinfo) XT_CONNTRACK_STATE_BIT(ctinfo) |
12 | #define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2)) | 11 | #define IPT_CONNTRACK_STATE_INVALID XT_CONNTRACK_STATE_INVALID |
13 | #define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3)) | ||
14 | 12 | ||
15 | /* flags, invflags: */ | 13 | #define IPT_CONNTRACK_STATE_SNAT XT_CONNTRACK_STATE_SNAT |
16 | #define IPT_CONNTRACK_STATE 0x01 | 14 | #define IPT_CONNTRACK_STATE_DNAT XT_CONNTRACK_STATE_DNAT |
17 | #define IPT_CONNTRACK_PROTO 0x02 | 15 | #define IPT_CONNTRACK_STATE_UNTRACKED XT_CONNTRACK_STATE_UNTRACKED |
18 | #define IPT_CONNTRACK_ORIGSRC 0x04 | ||
19 | #define IPT_CONNTRACK_ORIGDST 0x08 | ||
20 | #define IPT_CONNTRACK_REPLSRC 0x10 | ||
21 | #define IPT_CONNTRACK_REPLDST 0x20 | ||
22 | #define IPT_CONNTRACK_STATUS 0x40 | ||
23 | #define IPT_CONNTRACK_EXPIRES 0x80 | ||
24 | |||
25 | /* This is exposed to userspace, so remains frozen in time. */ | ||
26 | struct ip_conntrack_old_tuple | ||
27 | { | ||
28 | struct { | ||
29 | __u32 ip; | ||
30 | union { | ||
31 | __u16 all; | ||
32 | } u; | ||
33 | } src; | ||
34 | |||
35 | struct { | ||
36 | __u32 ip; | ||
37 | union { | ||
38 | __u16 all; | ||
39 | } u; | ||
40 | |||
41 | /* The protocol. */ | ||
42 | u16 protonum; | ||
43 | } dst; | ||
44 | }; | ||
45 | 16 | ||
46 | struct ipt_conntrack_info | 17 | /* flags, invflags: */ |
47 | { | 18 | #define IPT_CONNTRACK_STATE XT_CONNTRACK_STATE |
48 | unsigned int statemask, statusmask; | 19 | #define IPT_CONNTRACK_PROTO XT_CONNTRACK_PROTO |
49 | 20 | #define IPT_CONNTRACK_ORIGSRC XT_CONNTRACK_ORIGSRC | |
50 | struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX]; | 21 | #define IPT_CONNTRACK_ORIGDST XT_CONNTRACK_ORIGDST |
51 | struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX]; | 22 | #define IPT_CONNTRACK_REPLSRC XT_CONNTRACK_REPLSRC |
52 | 23 | #define IPT_CONNTRACK_REPLDST XT_CONNTRACK_REPLDST | |
53 | unsigned long expires_min, expires_max; | 24 | #define IPT_CONNTRACK_STATUS XT_CONNTRACK_STATUS |
54 | 25 | #define IPT_CONNTRACK_EXPIRES XT_CONNTRACK_EXPIRES | |
55 | /* Flags word */ | 26 | |
56 | u_int8_t flags; | 27 | #define ipt_conntrack_info xt_conntrack_info |
57 | /* Inverse flags */ | ||
58 | u_int8_t invflags; | ||
59 | }; | ||
60 | #endif /*_IPT_CONNTRACK_H*/ | 28 | #endif /*_IPT_CONNTRACK_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_dccp.h b/include/linux/netfilter_ipv4/ipt_dccp.h index 3cb3a522e62b..e70d11e1f53c 100644 --- a/include/linux/netfilter_ipv4/ipt_dccp.h +++ b/include/linux/netfilter_ipv4/ipt_dccp.h | |||
@@ -1,23 +1,15 @@ | |||
1 | #ifndef _IPT_DCCP_H_ | 1 | #ifndef _IPT_DCCP_H_ |
2 | #define _IPT_DCCP_H_ | 2 | #define _IPT_DCCP_H_ |
3 | 3 | ||
4 | #define IPT_DCCP_SRC_PORTS 0x01 | 4 | #include <linux/netfilter/xt_dccp.h> |
5 | #define IPT_DCCP_DEST_PORTS 0x02 | 5 | #define IPT_DCCP_SRC_PORTS XT_DCCP_SRC_PORTS |
6 | #define IPT_DCCP_TYPE 0x04 | 6 | #define IPT_DCCP_DEST_PORTS XT_DCCP_DEST_PORTS |
7 | #define IPT_DCCP_OPTION 0x08 | 7 | #define IPT_DCCP_TYPE XT_DCCP_TYPE |
8 | #define IPT_DCCP_OPTION XT_DCCP_OPTION | ||
8 | 9 | ||
9 | #define IPT_DCCP_VALID_FLAGS 0x0f | 10 | #define IPT_DCCP_VALID_FLAGS XT_DCCP_VALID_FLAGS |
10 | 11 | ||
11 | struct ipt_dccp_info { | 12 | #define ipt_dccp_info xt_dccp_info |
12 | u_int16_t dpts[2]; /* Min, Max */ | ||
13 | u_int16_t spts[2]; /* Min, Max */ | ||
14 | |||
15 | u_int16_t flags; | ||
16 | u_int16_t invflags; | ||
17 | |||
18 | u_int16_t typemask; | ||
19 | u_int8_t option; | ||
20 | }; | ||
21 | 13 | ||
22 | #endif /* _IPT_DCCP_H_ */ | 14 | #endif /* _IPT_DCCP_H_ */ |
23 | 15 | ||
diff --git a/include/linux/netfilter_ipv4/ipt_helper.h b/include/linux/netfilter_ipv4/ipt_helper.h index 6f12ecb8c93d..80452c218551 100644 --- a/include/linux/netfilter_ipv4/ipt_helper.h +++ b/include/linux/netfilter_ipv4/ipt_helper.h | |||
@@ -1,8 +1,7 @@ | |||
1 | #ifndef _IPT_HELPER_H | 1 | #ifndef _IPT_HELPER_H |
2 | #define _IPT_HELPER_H | 2 | #define _IPT_HELPER_H |
3 | 3 | ||
4 | struct ipt_helper_info { | 4 | #include <linux/netfilter/xt_helper.h> |
5 | int invert; | 5 | #define ipt_helper_info xt_helper_info |
6 | char name[30]; | 6 | |
7 | }; | ||
8 | #endif /* _IPT_HELPER_H */ | 7 | #endif /* _IPT_HELPER_H */ |
diff --git a/include/linux/netfilter_ipv4/ipt_length.h b/include/linux/netfilter_ipv4/ipt_length.h index 6e0885229615..9b45206ffcef 100644 --- a/include/linux/netfilter_ipv4/ipt_length.h +++ b/include/linux/netfilter_ipv4/ipt_length.h | |||
@@ -1,9 +1,7 @@ | |||
1 | #ifndef _IPT_LENGTH_H | 1 | #ifndef _IPT_LENGTH_H |
2 | #define _IPT_LENGTH_H | 2 | #define _IPT_LENGTH_H |
3 | 3 | ||
4 | struct ipt_length_info { | 4 | #include <linux/netfilter/xt_length.h> |
5 | u_int16_t min, max; | 5 | #define ipt_length_info xt_length_info |
6 | u_int8_t invert; | ||
7 | }; | ||
8 | 6 | ||
9 | #endif /*_IPT_LENGTH_H*/ | 7 | #endif /*_IPT_LENGTH_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_limit.h b/include/linux/netfilter_ipv4/ipt_limit.h index 256453409e21..92f5cd07bbc4 100644 --- a/include/linux/netfilter_ipv4/ipt_limit.h +++ b/include/linux/netfilter_ipv4/ipt_limit.h | |||
@@ -1,21 +1,8 @@ | |||
1 | #ifndef _IPT_RATE_H | 1 | #ifndef _IPT_RATE_H |
2 | #define _IPT_RATE_H | 2 | #define _IPT_RATE_H |
3 | 3 | ||
4 | /* timings are in milliseconds. */ | 4 | #include <linux/netfilter/xt_limit.h> |
5 | #define IPT_LIMIT_SCALE 10000 | 5 | #define IPT_LIMIT_SCALE XT_LIMIT_SCALE |
6 | #define ipt_rateinfo xt_rateinfo | ||
6 | 7 | ||
7 | /* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 | ||
8 | seconds, or one every 59 hours. */ | ||
9 | struct ipt_rateinfo { | ||
10 | u_int32_t avg; /* Average secs between packets * scale */ | ||
11 | u_int32_t burst; /* Period multiplier for upper limit. */ | ||
12 | |||
13 | /* Used internally by the kernel */ | ||
14 | unsigned long prev; | ||
15 | u_int32_t credit; | ||
16 | u_int32_t credit_cap, cost; | ||
17 | |||
18 | /* Ugly, ugly fucker. */ | ||
19 | struct ipt_rateinfo *master; | ||
20 | }; | ||
21 | #endif /*_IPT_RATE_H*/ | 8 | #endif /*_IPT_RATE_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_mac.h b/include/linux/netfilter_ipv4/ipt_mac.h index f8d5b8e7ccdb..b186008a3c47 100644 --- a/include/linux/netfilter_ipv4/ipt_mac.h +++ b/include/linux/netfilter_ipv4/ipt_mac.h | |||
@@ -1,8 +1,7 @@ | |||
1 | #ifndef _IPT_MAC_H | 1 | #ifndef _IPT_MAC_H |
2 | #define _IPT_MAC_H | 2 | #define _IPT_MAC_H |
3 | 3 | ||
4 | struct ipt_mac_info { | 4 | #include <linux/netfilter/xt_mac.h> |
5 | unsigned char srcaddr[ETH_ALEN]; | 5 | #define ipt_mac_info xt_mac_info |
6 | int invert; | 6 | |
7 | }; | ||
8 | #endif /*_IPT_MAC_H*/ | 7 | #endif /*_IPT_MAC_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_mark.h b/include/linux/netfilter_ipv4/ipt_mark.h index f3952b563d4c..bfde67c61224 100644 --- a/include/linux/netfilter_ipv4/ipt_mark.h +++ b/include/linux/netfilter_ipv4/ipt_mark.h | |||
@@ -1,9 +1,9 @@ | |||
1 | #ifndef _IPT_MARK_H | 1 | #ifndef _IPT_MARK_H |
2 | #define _IPT_MARK_H | 2 | #define _IPT_MARK_H |
3 | 3 | ||
4 | struct ipt_mark_info { | 4 | /* Backwards compatibility for old userspace */ |
5 | unsigned long mark, mask; | 5 | #include <linux/netfilter/xt_mark.h> |
6 | u_int8_t invert; | 6 | |
7 | }; | 7 | #define ipt_mark_info xt_mark_info |
8 | 8 | ||
9 | #endif /*_IPT_MARK_H*/ | 9 | #endif /*_IPT_MARK_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_physdev.h b/include/linux/netfilter_ipv4/ipt_physdev.h index 7538c8655ec0..2400e7140f26 100644 --- a/include/linux/netfilter_ipv4/ipt_physdev.h +++ b/include/linux/netfilter_ipv4/ipt_physdev.h | |||
@@ -1,24 +1,17 @@ | |||
1 | #ifndef _IPT_PHYSDEV_H | 1 | #ifndef _IPT_PHYSDEV_H |
2 | #define _IPT_PHYSDEV_H | 2 | #define _IPT_PHYSDEV_H |
3 | 3 | ||
4 | #ifdef __KERNEL__ | 4 | /* Backwards compatibility for old userspace */ |
5 | #include <linux/if.h> | ||
6 | #endif | ||
7 | 5 | ||
8 | #define IPT_PHYSDEV_OP_IN 0x01 | 6 | #include <linux/netfilter/xt_physdev.h> |
9 | #define IPT_PHYSDEV_OP_OUT 0x02 | ||
10 | #define IPT_PHYSDEV_OP_BRIDGED 0x04 | ||
11 | #define IPT_PHYSDEV_OP_ISIN 0x08 | ||
12 | #define IPT_PHYSDEV_OP_ISOUT 0x10 | ||
13 | #define IPT_PHYSDEV_OP_MASK (0x20 - 1) | ||
14 | 7 | ||
15 | struct ipt_physdev_info { | 8 | #define IPT_PHYSDEV_OP_IN XT_PHYSDEV_OP_IN |
16 | char physindev[IFNAMSIZ]; | 9 | #define IPT_PHYSDEV_OP_OUT XT_PHYSDEV_OP_OUT |
17 | char in_mask[IFNAMSIZ]; | 10 | #define IPT_PHYSDEV_OP_BRIDGED XT_PHYSDEV_OP_BRIDGED |
18 | char physoutdev[IFNAMSIZ]; | 11 | #define IPT_PHYSDEV_OP_ISIN XT_PHYSDEV_OP_ISIN |
19 | char out_mask[IFNAMSIZ]; | 12 | #define IPT_PHYSDEV_OP_ISOUT XT_PHYSDEV_OP_ISOUT |
20 | u_int8_t invert; | 13 | #define IPT_PHYSDEV_OP_MASK XT_PHYSDEV_OP_MASK |
21 | u_int8_t bitmask; | 14 | |
22 | }; | 15 | #define ipt_physdev_info xt_physdev_info |
23 | 16 | ||
24 | #endif /*_IPT_PHYSDEV_H*/ | 17 | #endif /*_IPT_PHYSDEV_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_pkttype.h b/include/linux/netfilter_ipv4/ipt_pkttype.h index d53a65848683..ff1fbc949a0c 100644 --- a/include/linux/netfilter_ipv4/ipt_pkttype.h +++ b/include/linux/netfilter_ipv4/ipt_pkttype.h | |||
@@ -1,8 +1,7 @@ | |||
1 | #ifndef _IPT_PKTTYPE_H | 1 | #ifndef _IPT_PKTTYPE_H |
2 | #define _IPT_PKTTYPE_H | 2 | #define _IPT_PKTTYPE_H |
3 | 3 | ||
4 | struct ipt_pkttype_info { | 4 | #include <linux/netfilter/xt_pkttype.h> |
5 | int pkttype; | 5 | #define ipt_pkttype_info xt_pkttype_info |
6 | int invert; | 6 | |
7 | }; | ||
8 | #endif /*_IPT_PKTTYPE_H*/ | 7 | #endif /*_IPT_PKTTYPE_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_realm.h b/include/linux/netfilter_ipv4/ipt_realm.h index a4d6698723ac..b3996eaa0188 100644 --- a/include/linux/netfilter_ipv4/ipt_realm.h +++ b/include/linux/netfilter_ipv4/ipt_realm.h | |||
@@ -1,10 +1,7 @@ | |||
1 | #ifndef _IPT_REALM_H | 1 | #ifndef _IPT_REALM_H |
2 | #define _IPT_REALM_H | 2 | #define _IPT_REALM_H |
3 | 3 | ||
4 | struct ipt_realm_info { | 4 | #include <linux/netfilter/xt_realm.h> |
5 | u_int32_t id; | 5 | #define ipt_realm_info xt_realm_info |
6 | u_int32_t mask; | ||
7 | u_int8_t invert; | ||
8 | }; | ||
9 | 6 | ||
10 | #endif /* _IPT_REALM_H */ | 7 | #endif /* _IPT_REALM_H */ |
diff --git a/include/linux/netfilter_ipv4/ipt_state.h b/include/linux/netfilter_ipv4/ipt_state.h index 5df37868933d..a44a99cc28cc 100644 --- a/include/linux/netfilter_ipv4/ipt_state.h +++ b/include/linux/netfilter_ipv4/ipt_state.h | |||
@@ -1,13 +1,15 @@ | |||
1 | #ifndef _IPT_STATE_H | 1 | #ifndef _IPT_STATE_H |
2 | #define _IPT_STATE_H | 2 | #define _IPT_STATE_H |
3 | 3 | ||
4 | #define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) | 4 | /* Backwards compatibility for old userspace */ |
5 | #define IPT_STATE_INVALID (1 << 0) | ||
6 | 5 | ||
7 | #define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1)) | 6 | #include <linux/netfilter/xt_state.h> |
7 | |||
8 | #define IPT_STATE_BIT XT_STATE_BIT | ||
9 | #define IPT_STATE_INVALID XT_STATE_INVALID | ||
10 | |||
11 | #define IPT_STATE_UNTRACKED XT_STATE_UNTRACKED | ||
12 | |||
13 | #define ipt_state_info xt_state_info | ||
8 | 14 | ||
9 | struct ipt_state_info | ||
10 | { | ||
11 | unsigned int statemask; | ||
12 | }; | ||
13 | #endif /*_IPT_STATE_H*/ | 15 | #endif /*_IPT_STATE_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_string.h b/include/linux/netfilter_ipv4/ipt_string.h index a265f6e44eab..c26de3059903 100644 --- a/include/linux/netfilter_ipv4/ipt_string.h +++ b/include/linux/netfilter_ipv4/ipt_string.h | |||
@@ -1,18 +1,10 @@ | |||
1 | #ifndef _IPT_STRING_H | 1 | #ifndef _IPT_STRING_H |
2 | #define _IPT_STRING_H | 2 | #define _IPT_STRING_H |
3 | 3 | ||
4 | #define IPT_STRING_MAX_PATTERN_SIZE 128 | 4 | #include <linux/netfilter/xt_string.h> |
5 | #define IPT_STRING_MAX_ALGO_NAME_SIZE 16 | ||
6 | 5 | ||
7 | struct ipt_string_info | 6 | #define IPT_STRING_MAX_PATTERN_SIZE XT_STRING_MAX_PATTERN_SIZE |
8 | { | 7 | #define IPT_STRING_MAX_ALGO_NAME_SIZE XT_STRING_MAX_ALGO_NAME_SIZE |
9 | u_int16_t from_offset; | 8 | #define ipt_string_info xt_string_info |
10 | u_int16_t to_offset; | ||
11 | char algo[IPT_STRING_MAX_ALGO_NAME_SIZE]; | ||
12 | char pattern[IPT_STRING_MAX_PATTERN_SIZE]; | ||
13 | u_int8_t patlen; | ||
14 | u_int8_t invert; | ||
15 | struct ts_config __attribute__((aligned(8))) *config; | ||
16 | }; | ||
17 | 9 | ||
18 | #endif /*_IPT_STRING_H*/ | 10 | #endif /*_IPT_STRING_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_tcpmss.h b/include/linux/netfilter_ipv4/ipt_tcpmss.h index e2b14397f701..18bbc8e8e009 100644 --- a/include/linux/netfilter_ipv4/ipt_tcpmss.h +++ b/include/linux/netfilter_ipv4/ipt_tcpmss.h | |||
@@ -1,9 +1,7 @@ | |||
1 | #ifndef _IPT_TCPMSS_MATCH_H | 1 | #ifndef _IPT_TCPMSS_MATCH_H |
2 | #define _IPT_TCPMSS_MATCH_H | 2 | #define _IPT_TCPMSS_MATCH_H |
3 | 3 | ||
4 | struct ipt_tcpmss_match_info { | 4 | #include <linux/netfilter/xt_tcpmss.h> |
5 | u_int16_t mss_min, mss_max; | 5 | #define ipt_tcpmss_match_info xt_tcpmss_match_info |
6 | u_int8_t invert; | ||
7 | }; | ||
8 | 6 | ||
9 | #endif /*_IPT_TCPMSS_MATCH_H*/ | 7 | #endif /*_IPT_TCPMSS_MATCH_H*/ |
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index c163ba31aab7..f249b574f0fa 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h | |||
@@ -25,8 +25,15 @@ | |||
25 | #include <linux/compiler.h> | 25 | #include <linux/compiler.h> |
26 | #include <linux/netfilter_ipv6.h> | 26 | #include <linux/netfilter_ipv6.h> |
27 | 27 | ||
28 | #define IP6T_FUNCTION_MAXNAMELEN 30 | 28 | #include <linux/netfilter/x_tables.h> |
29 | #define IP6T_TABLE_MAXNAMELEN 32 | 29 | |
30 | #define IP6T_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN | ||
31 | #define IP6T_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN | ||
32 | |||
33 | #define ip6t_match xt_match | ||
34 | #define ip6t_target xt_target | ||
35 | #define ip6t_table xt_table | ||
36 | #define ip6t_get_revision xt_get_revision | ||
30 | 37 | ||
31 | /* Yes, Virginia, you have to zero the padding. */ | 38 | /* Yes, Virginia, you have to zero the padding. */ |
32 | struct ip6t_ip6 { | 39 | struct ip6t_ip6 { |
@@ -104,10 +111,7 @@ struct ip6t_standard_target | |||
104 | int verdict; | 111 | int verdict; |
105 | }; | 112 | }; |
106 | 113 | ||
107 | struct ip6t_counters | 114 | #define ip6t_counters xt_counters |
108 | { | ||
109 | u_int64_t pcnt, bcnt; /* Packet and byte counters */ | ||
110 | }; | ||
111 | 115 | ||
112 | /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */ | 116 | /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */ |
113 | #define IP6T_F_PROTO 0x01 /* Set if rule cares about upper | 117 | #define IP6T_F_PROTO 0x01 /* Set if rule cares about upper |
@@ -123,7 +127,7 @@ struct ip6t_counters | |||
123 | #define IP6T_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ | 127 | #define IP6T_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ |
124 | #define IP6T_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ | 128 | #define IP6T_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ |
125 | #define IP6T_INV_FRAG 0x20 /* Invert the sense of FRAG. */ | 129 | #define IP6T_INV_FRAG 0x20 /* Invert the sense of FRAG. */ |
126 | #define IP6T_INV_PROTO 0x40 /* Invert the sense of PROTO. */ | 130 | #define IP6T_INV_PROTO XT_INV_PROTO |
127 | #define IP6T_INV_MASK 0x7F /* All possible flag bits mask. */ | 131 | #define IP6T_INV_MASK 0x7F /* All possible flag bits mask. */ |
128 | 132 | ||
129 | /* This structure defines each of the firewall rules. Consists of 3 | 133 | /* This structure defines each of the firewall rules. Consists of 3 |
@@ -145,7 +149,7 @@ struct ip6t_entry | |||
145 | unsigned int comefrom; | 149 | unsigned int comefrom; |
146 | 150 | ||
147 | /* Packet and byte counters. */ | 151 | /* Packet and byte counters. */ |
148 | struct ip6t_counters counters; | 152 | struct xt_counters counters; |
149 | 153 | ||
150 | /* The matches (if any), then the target. */ | 154 | /* The matches (if any), then the target. */ |
151 | unsigned char elems[0]; | 155 | unsigned char elems[0]; |
@@ -155,54 +159,41 @@ struct ip6t_entry | |||
155 | * New IP firewall options for [gs]etsockopt at the RAW IP level. | 159 | * New IP firewall options for [gs]etsockopt at the RAW IP level. |
156 | * Unlike BSD Linux inherits IP options so you don't have to use | 160 | * Unlike BSD Linux inherits IP options so you don't have to use |
157 | * a raw socket for this. Instead we check rights in the calls. */ | 161 | * a raw socket for this. Instead we check rights in the calls. */ |
158 | #define IP6T_BASE_CTL 64 /* base for firewall socket options */ | 162 | #define IP6T_BASE_CTL XT_BASE_CTL |
159 | 163 | ||
160 | #define IP6T_SO_SET_REPLACE (IP6T_BASE_CTL) | 164 | #define IP6T_SO_SET_REPLACE XT_SO_SET_REPLACE |
161 | #define IP6T_SO_SET_ADD_COUNTERS (IP6T_BASE_CTL + 1) | 165 | #define IP6T_SO_SET_ADD_COUNTERS XT_SO_SET_ADD_COUNTERS |
162 | #define IP6T_SO_SET_MAX IP6T_SO_SET_ADD_COUNTERS | 166 | #define IP6T_SO_SET_MAX XT_SO_SET_MAX |
163 | 167 | ||
164 | #define IP6T_SO_GET_INFO (IP6T_BASE_CTL) | 168 | #define IP6T_SO_GET_INFO XT_SO_GET_INFO |
165 | #define IP6T_SO_GET_ENTRIES (IP6T_BASE_CTL + 1) | 169 | #define IP6T_SO_GET_ENTRIES XT_SO_GET_ENTRIES |
166 | #define IP6T_SO_GET_REVISION_MATCH (IP6T_BASE_CTL + 2) | 170 | #define IP6T_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH |
167 | #define IP6T_SO_GET_REVISION_TARGET (IP6T_BASE_CTL + 3) | 171 | #define IP6T_SO_GET_REVISION_TARGET XT_SO_GET_REVISION_TARGET |
168 | #define IP6T_SO_GET_MAX IP6T_SO_GET_REVISION_TARGET | 172 | #define IP6T_SO_GET_MAX XT_SO_GET_REVISION_TARGET |
169 | 173 | ||
170 | /* CONTINUE verdict for targets */ | 174 | /* CONTINUE verdict for targets */ |
171 | #define IP6T_CONTINUE 0xFFFFFFFF | 175 | #define IP6T_CONTINUE XT_CONTINUE |
172 | 176 | ||
173 | /* For standard target */ | 177 | /* For standard target */ |
174 | #define IP6T_RETURN (-NF_REPEAT - 1) | 178 | #define IP6T_RETURN XT_RETURN |
175 | 179 | ||
176 | /* TCP matching stuff */ | 180 | /* TCP/UDP matching stuff */ |
177 | struct ip6t_tcp | 181 | #include <linux/netfilter/xt_tcpudp.h> |
178 | { | 182 | |
179 | u_int16_t spts[2]; /* Source port range. */ | 183 | #define ip6t_tcp xt_tcp |
180 | u_int16_t dpts[2]; /* Destination port range. */ | 184 | #define ip6t_udp xt_udp |
181 | u_int8_t option; /* TCP Option iff non-zero*/ | ||
182 | u_int8_t flg_mask; /* TCP flags mask byte */ | ||
183 | u_int8_t flg_cmp; /* TCP flags compare byte */ | ||
184 | u_int8_t invflags; /* Inverse flags */ | ||
185 | }; | ||
186 | 185 | ||
187 | /* Values for "inv" field in struct ipt_tcp. */ | 186 | /* Values for "inv" field in struct ipt_tcp. */ |
188 | #define IP6T_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ | 187 | #define IP6T_TCP_INV_SRCPT XT_TCP_INV_SRCPT |
189 | #define IP6T_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ | 188 | #define IP6T_TCP_INV_DSTPT XT_TCP_INV_DSTPT |
190 | #define IP6T_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */ | 189 | #define IP6T_TCP_INV_FLAGS XT_TCP_INV_FLAGS |
191 | #define IP6T_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */ | 190 | #define IP6T_TCP_INV_OPTION XT_TCP_INV_OPTION |
192 | #define IP6T_TCP_INV_MASK 0x0F /* All possible flags. */ | 191 | #define IP6T_TCP_INV_MASK XT_TCP_INV_MASK |
193 | |||
194 | /* UDP matching stuff */ | ||
195 | struct ip6t_udp | ||
196 | { | ||
197 | u_int16_t spts[2]; /* Source port range. */ | ||
198 | u_int16_t dpts[2]; /* Destination port range. */ | ||
199 | u_int8_t invflags; /* Inverse flags */ | ||
200 | }; | ||
201 | 192 | ||
202 | /* Values for "invflags" field in struct ipt_udp. */ | 193 | /* Values for "invflags" field in struct ipt_udp. */ |
203 | #define IP6T_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ | 194 | #define IP6T_UDP_INV_SRCPT XT_UDP_INV_SRCPT |
204 | #define IP6T_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ | 195 | #define IP6T_UDP_INV_DSTPT XT_UDP_INV_DSTPT |
205 | #define IP6T_UDP_INV_MASK 0x03 /* All possible flags. */ | 196 | #define IP6T_UDP_INV_MASK XT_UDP_INV_MASK |
206 | 197 | ||
207 | /* ICMP matching stuff */ | 198 | /* ICMP matching stuff */ |
208 | struct ip6t_icmp | 199 | struct ip6t_icmp |
@@ -264,23 +255,14 @@ struct ip6t_replace | |||
264 | /* Number of counters (must be equal to current number of entries). */ | 255 | /* Number of counters (must be equal to current number of entries). */ |
265 | unsigned int num_counters; | 256 | unsigned int num_counters; |
266 | /* The old entries' counters. */ | 257 | /* The old entries' counters. */ |
267 | struct ip6t_counters __user *counters; | 258 | struct xt_counters __user *counters; |
268 | 259 | ||
269 | /* The entries (hang off end: not really an array). */ | 260 | /* The entries (hang off end: not really an array). */ |
270 | struct ip6t_entry entries[0]; | 261 | struct ip6t_entry entries[0]; |
271 | }; | 262 | }; |
272 | 263 | ||
273 | /* The argument to IP6T_SO_ADD_COUNTERS. */ | 264 | /* The argument to IP6T_SO_ADD_COUNTERS. */ |
274 | struct ip6t_counters_info | 265 | #define ip6t_counters_info xt_counters_info |
275 | { | ||
276 | /* Which table. */ | ||
277 | char name[IP6T_TABLE_MAXNAMELEN]; | ||
278 | |||
279 | unsigned int num_counters; | ||
280 | |||
281 | /* The counters (actually `number' of these). */ | ||
282 | struct ip6t_counters counters[0]; | ||
283 | }; | ||
284 | 266 | ||
285 | /* The argument to IP6T_SO_GET_ENTRIES. */ | 267 | /* The argument to IP6T_SO_GET_ENTRIES. */ |
286 | struct ip6t_get_entries | 268 | struct ip6t_get_entries |
@@ -295,19 +277,10 @@ struct ip6t_get_entries | |||
295 | struct ip6t_entry entrytable[0]; | 277 | struct ip6t_entry entrytable[0]; |
296 | }; | 278 | }; |
297 | 279 | ||
298 | /* The argument to IP6T_SO_GET_REVISION_*. Returns highest revision | ||
299 | * kernel supports, if >= revision. */ | ||
300 | struct ip6t_get_revision | ||
301 | { | ||
302 | char name[IP6T_FUNCTION_MAXNAMELEN-1]; | ||
303 | |||
304 | u_int8_t revision; | ||
305 | }; | ||
306 | |||
307 | /* Standard return verdict, or do jump. */ | 280 | /* Standard return verdict, or do jump. */ |
308 | #define IP6T_STANDARD_TARGET "" | 281 | #define IP6T_STANDARD_TARGET XT_STANDARD_TARGET |
309 | /* Error verdict. */ | 282 | /* Error verdict. */ |
310 | #define IP6T_ERROR_TARGET "ERROR" | 283 | #define IP6T_ERROR_TARGET XT_ERROR_TARGET |
311 | 284 | ||
312 | /* Helper functions */ | 285 | /* Helper functions */ |
313 | static __inline__ struct ip6t_entry_target * | 286 | static __inline__ struct ip6t_entry_target * |
@@ -361,104 +334,11 @@ ip6t_get_target(struct ip6t_entry *e) | |||
361 | #include <linux/init.h> | 334 | #include <linux/init.h> |
362 | extern void ip6t_init(void) __init; | 335 | extern void ip6t_init(void) __init; |
363 | 336 | ||
364 | struct ip6t_match | 337 | #define ip6t_register_target(tgt) xt_register_target(AF_INET6, tgt) |
365 | { | 338 | #define ip6t_unregister_target(tgt) xt_unregister_target(AF_INET6, tgt) |
366 | struct list_head list; | ||
367 | |||
368 | const char name[IP6T_FUNCTION_MAXNAMELEN-1]; | ||
369 | |||
370 | u_int8_t revision; | ||
371 | |||
372 | /* Return true or false: return FALSE and set *hotdrop = 1 to | ||
373 | force immediate packet drop. */ | ||
374 | /* Arguments changed since 2.6.9, as this must now handle | ||
375 | non-linear skb, using skb_header_pointer and | ||
376 | skb_ip_make_writable. */ | ||
377 | int (*match)(const struct sk_buff *skb, | ||
378 | const struct net_device *in, | ||
379 | const struct net_device *out, | ||
380 | const void *matchinfo, | ||
381 | int offset, | ||
382 | unsigned int protoff, | ||
383 | int *hotdrop); | ||
384 | |||
385 | /* Called when user tries to insert an entry of this type. */ | ||
386 | /* Should return true or false. */ | ||
387 | int (*checkentry)(const char *tablename, | ||
388 | const struct ip6t_ip6 *ip, | ||
389 | void *matchinfo, | ||
390 | unsigned int matchinfosize, | ||
391 | unsigned int hook_mask); | ||
392 | |||
393 | /* Called when entry of this type deleted. */ | ||
394 | void (*destroy)(void *matchinfo, unsigned int matchinfosize); | ||
395 | |||
396 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
397 | struct module *me; | ||
398 | }; | ||
399 | |||
400 | /* Registration hooks for targets. */ | ||
401 | struct ip6t_target | ||
402 | { | ||
403 | struct list_head list; | ||
404 | |||
405 | const char name[IP6T_FUNCTION_MAXNAMELEN-1]; | ||
406 | |||
407 | u_int8_t revision; | ||
408 | |||
409 | /* Returns verdict. Argument order changed since 2.6.9, as this | ||
410 | must now handle non-linear skbs, using skb_copy_bits and | ||
411 | skb_ip_make_writable. */ | ||
412 | unsigned int (*target)(struct sk_buff **pskb, | ||
413 | const struct net_device *in, | ||
414 | const struct net_device *out, | ||
415 | unsigned int hooknum, | ||
416 | const void *targinfo, | ||
417 | void *userdata); | ||
418 | |||
419 | /* Called when user tries to insert an entry of this type: | ||
420 | hook_mask is a bitmask of hooks from which it can be | ||
421 | called. */ | ||
422 | /* Should return true or false. */ | ||
423 | int (*checkentry)(const char *tablename, | ||
424 | const struct ip6t_entry *e, | ||
425 | void *targinfo, | ||
426 | unsigned int targinfosize, | ||
427 | unsigned int hook_mask); | ||
428 | |||
429 | /* Called when entry of this type deleted. */ | ||
430 | void (*destroy)(void *targinfo, unsigned int targinfosize); | ||
431 | |||
432 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
433 | struct module *me; | ||
434 | }; | ||
435 | |||
436 | extern int ip6t_register_target(struct ip6t_target *target); | ||
437 | extern void ip6t_unregister_target(struct ip6t_target *target); | ||
438 | |||
439 | extern int ip6t_register_match(struct ip6t_match *match); | ||
440 | extern void ip6t_unregister_match(struct ip6t_match *match); | ||
441 | 339 | ||
442 | /* Furniture shopping... */ | 340 | #define ip6t_register_match(match) xt_register_match(AF_INET6, match) |
443 | struct ip6t_table | 341 | #define ip6t_unregister_match(match) xt_unregister_match(AF_INET6, match) |
444 | { | ||
445 | struct list_head list; | ||
446 | |||
447 | /* A unique name... */ | ||
448 | char name[IP6T_TABLE_MAXNAMELEN]; | ||
449 | |||
450 | /* What hooks you will enter on */ | ||
451 | unsigned int valid_hooks; | ||
452 | |||
453 | /* Lock for the curtain */ | ||
454 | rwlock_t lock; | ||
455 | |||
456 | /* Man behind the curtain... */ | ||
457 | struct ip6t_table_info *private; | ||
458 | |||
459 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
460 | struct module *me; | ||
461 | }; | ||
462 | 342 | ||
463 | extern int ip6t_register_table(struct ip6t_table *table, | 343 | extern int ip6t_register_table(struct ip6t_table *table, |
464 | const struct ip6t_replace *repl); | 344 | const struct ip6t_replace *repl); |
diff --git a/include/linux/netfilter_ipv6/ip6t_MARK.h b/include/linux/netfilter_ipv6/ip6t_MARK.h index 7ade8d8f5246..7cf629a8ab92 100644 --- a/include/linux/netfilter_ipv6/ip6t_MARK.h +++ b/include/linux/netfilter_ipv6/ip6t_MARK.h | |||
@@ -1,8 +1,9 @@ | |||
1 | #ifndef _IP6T_MARK_H_target | 1 | #ifndef _IP6T_MARK_H_target |
2 | #define _IP6T_MARK_H_target | 2 | #define _IP6T_MARK_H_target |
3 | 3 | ||
4 | struct ip6t_mark_target_info { | 4 | /* Backwards compatibility for old userspace */ |
5 | unsigned long mark; | 5 | #include <linux/netfilter/xt_MARK.h> |
6 | }; | ||
7 | 6 | ||
8 | #endif /*_IPT_MARK_H_target*/ | 7 | #define ip6t_mark_target_info xt_mark_target_info |
8 | |||
9 | #endif /*_IP6T_MARK_H_target*/ | ||
diff --git a/include/linux/netfilter_ipv6/ip6t_length.h b/include/linux/netfilter_ipv6/ip6t_length.h index 7fc09f9f9d63..9e9689d03ed7 100644 --- a/include/linux/netfilter_ipv6/ip6t_length.h +++ b/include/linux/netfilter_ipv6/ip6t_length.h | |||
@@ -1,10 +1,8 @@ | |||
1 | #ifndef _IP6T_LENGTH_H | 1 | #ifndef _IP6T_LENGTH_H |
2 | #define _IP6T_LENGTH_H | 2 | #define _IP6T_LENGTH_H |
3 | 3 | ||
4 | struct ip6t_length_info { | 4 | #include <linux/netfilter/xt_length.h> |
5 | u_int16_t min, max; | 5 | #define ip6t_length_info xt_length_info |
6 | u_int8_t invert; | ||
7 | }; | ||
8 | 6 | ||
9 | #endif /*_IP6T_LENGTH_H*/ | 7 | #endif /*_IP6T_LENGTH_H*/ |
10 | 8 | ||
diff --git a/include/linux/netfilter_ipv6/ip6t_limit.h b/include/linux/netfilter_ipv6/ip6t_limit.h index f2866e50f3b4..487e5ea342c6 100644 --- a/include/linux/netfilter_ipv6/ip6t_limit.h +++ b/include/linux/netfilter_ipv6/ip6t_limit.h | |||
@@ -1,21 +1,8 @@ | |||
1 | #ifndef _IP6T_RATE_H | 1 | #ifndef _IP6T_RATE_H |
2 | #define _IP6T_RATE_H | 2 | #define _IP6T_RATE_H |
3 | 3 | ||
4 | /* timings are in milliseconds. */ | 4 | #include <linux/netfilter/xt_limit.h> |
5 | #define IP6T_LIMIT_SCALE 10000 | 5 | #define IP6T_LIMIT_SCALE XT_LIMIT_SCALE |
6 | #define ip6t_rateinfo xt_rateinfo | ||
6 | 7 | ||
7 | /* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 | 8 | #endif /*_IP6T_RATE_H*/ |
8 | seconds, or one every 59 hours. */ | ||
9 | struct ip6t_rateinfo { | ||
10 | u_int32_t avg; /* Average secs between packets * scale */ | ||
11 | u_int32_t burst; /* Period multiplier for upper limit. */ | ||
12 | |||
13 | /* Used internally by the kernel */ | ||
14 | unsigned long prev; | ||
15 | u_int32_t credit; | ||
16 | u_int32_t credit_cap, cost; | ||
17 | |||
18 | /* Ugly, ugly fucker. */ | ||
19 | struct ip6t_rateinfo *master; | ||
20 | }; | ||
21 | #endif /*_IPT_RATE_H*/ | ||
diff --git a/include/linux/netfilter_ipv6/ip6t_mac.h b/include/linux/netfilter_ipv6/ip6t_mac.h index 87c088c21848..ac58e83e9423 100644 --- a/include/linux/netfilter_ipv6/ip6t_mac.h +++ b/include/linux/netfilter_ipv6/ip6t_mac.h | |||
@@ -1,8 +1,7 @@ | |||
1 | #ifndef _IP6T_MAC_H | 1 | #ifndef _IP6T_MAC_H |
2 | #define _IP6T_MAC_H | 2 | #define _IP6T_MAC_H |
3 | 3 | ||
4 | struct ip6t_mac_info { | 4 | #include <linux/netfilter/xt_mac.h> |
5 | unsigned char srcaddr[ETH_ALEN]; | 5 | #define ip6t_mac_info xt_mac_info |
6 | int invert; | 6 | |
7 | }; | 7 | #endif /*_IP6T_MAC_H*/ |
8 | #endif /*_IPT_MAC_H*/ | ||
diff --git a/include/linux/netfilter_ipv6/ip6t_mark.h b/include/linux/netfilter_ipv6/ip6t_mark.h index a734441e1c19..ff204951ddc3 100644 --- a/include/linux/netfilter_ipv6/ip6t_mark.h +++ b/include/linux/netfilter_ipv6/ip6t_mark.h | |||
@@ -1,9 +1,9 @@ | |||
1 | #ifndef _IP6T_MARK_H | 1 | #ifndef _IP6T_MARK_H |
2 | #define _IP6T_MARK_H | 2 | #define _IP6T_MARK_H |
3 | 3 | ||
4 | struct ip6t_mark_info { | 4 | /* Backwards compatibility for old userspace */ |
5 | unsigned long mark, mask; | 5 | #include <linux/netfilter/xt_mark.h> |
6 | u_int8_t invert; | 6 | |
7 | }; | 7 | #define ip6t_mark_info xt_mark_info |
8 | 8 | ||
9 | #endif /*_IPT_MARK_H*/ | 9 | #endif /*_IPT_MARK_H*/ |
diff --git a/include/linux/netfilter_ipv6/ip6t_physdev.h b/include/linux/netfilter_ipv6/ip6t_physdev.h index c234731cd66b..c161c0a81b55 100644 --- a/include/linux/netfilter_ipv6/ip6t_physdev.h +++ b/include/linux/netfilter_ipv6/ip6t_physdev.h | |||
@@ -1,24 +1,17 @@ | |||
1 | #ifndef _IP6T_PHYSDEV_H | 1 | #ifndef _IP6T_PHYSDEV_H |
2 | #define _IP6T_PHYSDEV_H | 2 | #define _IP6T_PHYSDEV_H |
3 | 3 | ||
4 | #ifdef __KERNEL__ | 4 | /* Backwards compatibility for old userspace */ |
5 | #include <linux/if.h> | ||
6 | #endif | ||
7 | 5 | ||
8 | #define IP6T_PHYSDEV_OP_IN 0x01 | 6 | #include <linux/netfilter/xt_physdev.h> |
9 | #define IP6T_PHYSDEV_OP_OUT 0x02 | ||
10 | #define IP6T_PHYSDEV_OP_BRIDGED 0x04 | ||
11 | #define IP6T_PHYSDEV_OP_ISIN 0x08 | ||
12 | #define IP6T_PHYSDEV_OP_ISOUT 0x10 | ||
13 | #define IP6T_PHYSDEV_OP_MASK (0x20 - 1) | ||
14 | 7 | ||
15 | struct ip6t_physdev_info { | 8 | #define IP6T_PHYSDEV_OP_IN XT_PHYSDEV_OP_IN |
16 | char physindev[IFNAMSIZ]; | 9 | #define IP6T_PHYSDEV_OP_OUT XT_PHYSDEV_OP_OUT |
17 | char in_mask[IFNAMSIZ]; | 10 | #define IP6T_PHYSDEV_OP_BRIDGED XT_PHYSDEV_OP_BRIDGED |
18 | char physoutdev[IFNAMSIZ]; | 11 | #define IP6T_PHYSDEV_OP_ISIN XT_PHYSDEV_OP_ISIN |
19 | char out_mask[IFNAMSIZ]; | 12 | #define IP6T_PHYSDEV_OP_ISOUT XT_PHYSDEV_OP_ISOUT |
20 | u_int8_t invert; | 13 | #define IP6T_PHYSDEV_OP_MASK XT_PHYSDEV_OP_MASK |
21 | u_int8_t bitmask; | 14 | |
22 | }; | 15 | #define ip6t_physdev_info xt_physdev_info |
23 | 16 | ||
24 | #endif /*_IP6T_PHYSDEV_H*/ | 17 | #endif /*_IP6T_PHYSDEV_H*/ |
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 74488e49166d..aa6322d45198 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h | |||
@@ -146,6 +146,11 @@ struct property; | |||
146 | extern void proc_device_tree_init(void); | 146 | extern void proc_device_tree_init(void); |
147 | extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); | 147 | extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); |
148 | extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop); | 148 | extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop); |
149 | extern void proc_device_tree_remove_prop(struct proc_dir_entry *pde, | ||
150 | struct property *prop); | ||
151 | extern void proc_device_tree_update_prop(struct proc_dir_entry *pde, | ||
152 | struct property *newprop, | ||
153 | struct property *oldprop); | ||
149 | #endif /* CONFIG_PROC_DEVICETREE */ | 154 | #endif /* CONFIG_PROC_DEVICETREE */ |
150 | 155 | ||
151 | extern struct proc_dir_entry *proc_symlink(const char *, | 156 | extern struct proc_dir_entry *proc_symlink(const char *, |
diff --git a/include/linux/socket.h b/include/linux/socket.h index 9f4019156fd8..b02dda4ee83d 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h | |||
@@ -186,6 +186,7 @@ struct ucred { | |||
186 | #define AF_PPPOX 24 /* PPPoX sockets */ | 186 | #define AF_PPPOX 24 /* PPPoX sockets */ |
187 | #define AF_WANPIPE 25 /* Wanpipe API Sockets */ | 187 | #define AF_WANPIPE 25 /* Wanpipe API Sockets */ |
188 | #define AF_LLC 26 /* Linux LLC */ | 188 | #define AF_LLC 26 /* Linux LLC */ |
189 | #define AF_TIPC 30 /* TIPC sockets */ | ||
189 | #define AF_BLUETOOTH 31 /* Bluetooth sockets */ | 190 | #define AF_BLUETOOTH 31 /* Bluetooth sockets */ |
190 | #define AF_MAX 32 /* For now.. */ | 191 | #define AF_MAX 32 /* For now.. */ |
191 | 192 | ||
@@ -218,6 +219,7 @@ struct ucred { | |||
218 | #define PF_PPPOX AF_PPPOX | 219 | #define PF_PPPOX AF_PPPOX |
219 | #define PF_WANPIPE AF_WANPIPE | 220 | #define PF_WANPIPE AF_WANPIPE |
220 | #define PF_LLC AF_LLC | 221 | #define PF_LLC AF_LLC |
222 | #define PF_TIPC AF_TIPC | ||
221 | #define PF_BLUETOOTH AF_BLUETOOTH | 223 | #define PF_BLUETOOTH AF_BLUETOOTH |
222 | #define PF_MAX AF_MAX | 224 | #define PF_MAX AF_MAX |
223 | 225 | ||
@@ -279,6 +281,7 @@ struct ucred { | |||
279 | #define SOL_LLC 268 | 281 | #define SOL_LLC 268 |
280 | #define SOL_DCCP 269 | 282 | #define SOL_DCCP 269 |
281 | #define SOL_NETLINK 270 | 283 | #define SOL_NETLINK 270 |
284 | #define SOL_TIPC 271 | ||
282 | 285 | ||
283 | /* IPX options */ | 286 | /* IPX options */ |
284 | #define IPX_TYPE 1 | 287 | #define IPX_TYPE 1 |
diff --git a/include/linux/tipc.h b/include/linux/tipc.h new file mode 100644 index 000000000000..243a15f54002 --- /dev/null +++ b/include/linux/tipc.h | |||
@@ -0,0 +1,212 @@ | |||
1 | /* | ||
2 | * include/linux/tipc.h: Include file for TIPC socket interface | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _LINUX_TIPC_H_ | ||
38 | #define _LINUX_TIPC_H_ | ||
39 | |||
40 | #include <linux/types.h> | ||
41 | |||
42 | /* | ||
43 | * TIPC addressing primitives | ||
44 | */ | ||
45 | |||
46 | struct tipc_portid { | ||
47 | __u32 ref; | ||
48 | __u32 node; | ||
49 | }; | ||
50 | |||
51 | struct tipc_name { | ||
52 | __u32 type; | ||
53 | __u32 instance; | ||
54 | }; | ||
55 | |||
56 | struct tipc_name_seq { | ||
57 | __u32 type; | ||
58 | __u32 lower; | ||
59 | __u32 upper; | ||
60 | }; | ||
61 | |||
62 | static inline __u32 tipc_addr(unsigned int zone, | ||
63 | unsigned int cluster, | ||
64 | unsigned int node) | ||
65 | { | ||
66 | return (zone << 24) | (cluster << 12) | node; | ||
67 | } | ||
68 | |||
69 | static inline unsigned int tipc_zone(__u32 addr) | ||
70 | { | ||
71 | return addr >> 24; | ||
72 | } | ||
73 | |||
74 | static inline unsigned int tipc_cluster(__u32 addr) | ||
75 | { | ||
76 | return (addr >> 12) & 0xfff; | ||
77 | } | ||
78 | |||
79 | static inline unsigned int tipc_node(__u32 addr) | ||
80 | { | ||
81 | return addr & 0xfff; | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | * Application-accessible port name types | ||
86 | */ | ||
87 | |||
88 | #define TIPC_CFG_SRV 0 /* configuration service name type */ | ||
89 | #define TIPC_TOP_SRV 1 /* topology service name type */ | ||
90 | #define TIPC_RESERVED_TYPES 64 /* lowest user-publishable name type */ | ||
91 | |||
92 | /* | ||
93 | * Publication scopes when binding port names and port name sequences | ||
94 | */ | ||
95 | |||
96 | #define TIPC_ZONE_SCOPE 1 | ||
97 | #define TIPC_CLUSTER_SCOPE 2 | ||
98 | #define TIPC_NODE_SCOPE 3 | ||
99 | |||
100 | /* | ||
101 | * Limiting values for messages | ||
102 | */ | ||
103 | |||
104 | #define TIPC_MAX_USER_MSG_SIZE 66000 | ||
105 | |||
106 | /* | ||
107 | * Message importance levels | ||
108 | */ | ||
109 | |||
110 | #define TIPC_LOW_IMPORTANCE 0 /* default */ | ||
111 | #define TIPC_MEDIUM_IMPORTANCE 1 | ||
112 | #define TIPC_HIGH_IMPORTANCE 2 | ||
113 | #define TIPC_CRITICAL_IMPORTANCE 3 | ||
114 | |||
115 | /* | ||
116 | * Msg rejection/connection shutdown reasons | ||
117 | */ | ||
118 | |||
119 | #define TIPC_OK 0 | ||
120 | #define TIPC_ERR_NO_NAME 1 | ||
121 | #define TIPC_ERR_NO_PORT 2 | ||
122 | #define TIPC_ERR_NO_NODE 3 | ||
123 | #define TIPC_ERR_OVERLOAD 4 | ||
124 | #define TIPC_CONN_SHUTDOWN 5 | ||
125 | |||
126 | /* | ||
127 | * TIPC topology subscription service definitions | ||
128 | */ | ||
129 | |||
130 | #define TIPC_SUB_PORTS 0x01 /* filter for port availability */ | ||
131 | #define TIPC_SUB_SERVICE 0x02 /* filter for service availability */ | ||
132 | #if 0 | ||
133 | /* The following filter options are not currently implemented */ | ||
134 | #define TIPC_SUB_NO_BIND_EVTS 0x04 /* filter out "publish" events */ | ||
135 | #define TIPC_SUB_NO_UNBIND_EVTS 0x08 /* filter out "withdraw" events */ | ||
136 | #define TIPC_SUB_SINGLE_EVT 0x10 /* expire after first event */ | ||
137 | #endif | ||
138 | |||
139 | #define TIPC_WAIT_FOREVER ~0 /* timeout for permanent subscription */ | ||
140 | |||
141 | struct tipc_subscr { | ||
142 | struct tipc_name_seq seq; /* name sequence of interest */ | ||
143 | __u32 timeout; /* subscription duration (in ms) */ | ||
144 | __u32 filter; /* bitmask of filter options */ | ||
145 | char usr_handle[8]; /* available for subscriber use */ | ||
146 | }; | ||
147 | |||
148 | #define TIPC_PUBLISHED 1 /* publication event */ | ||
149 | #define TIPC_WITHDRAWN 2 /* withdraw event */ | ||
150 | #define TIPC_SUBSCR_TIMEOUT 3 /* subscription timeout event */ | ||
151 | |||
152 | struct tipc_event { | ||
153 | __u32 event; /* event type */ | ||
154 | __u32 found_lower; /* matching name seq instances */ | ||
155 | __u32 found_upper; /* " " " " */ | ||
156 | struct tipc_portid port; /* associated port */ | ||
157 | struct tipc_subscr s; /* associated subscription */ | ||
158 | }; | ||
159 | |||
160 | /* | ||
161 | * Socket API | ||
162 | */ | ||
163 | |||
164 | #ifndef AF_TIPC | ||
165 | #define AF_TIPC 30 | ||
166 | #endif | ||
167 | |||
168 | #ifndef PF_TIPC | ||
169 | #define PF_TIPC AF_TIPC | ||
170 | #endif | ||
171 | |||
172 | #ifndef SOL_TIPC | ||
173 | #define SOL_TIPC 271 | ||
174 | #endif | ||
175 | |||
176 | #define TIPC_ADDR_NAMESEQ 1 | ||
177 | #define TIPC_ADDR_MCAST 1 | ||
178 | #define TIPC_ADDR_NAME 2 | ||
179 | #define TIPC_ADDR_ID 3 | ||
180 | |||
181 | struct sockaddr_tipc { | ||
182 | unsigned short family; | ||
183 | unsigned char addrtype; | ||
184 | signed char scope; | ||
185 | union { | ||
186 | struct tipc_portid id; | ||
187 | struct tipc_name_seq nameseq; | ||
188 | struct { | ||
189 | struct tipc_name name; | ||
190 | __u32 domain; /* 0: own zone */ | ||
191 | } name; | ||
192 | } addr; | ||
193 | }; | ||
194 | |||
195 | /* | ||
196 | * Ancillary data objects supported by recvmsg() | ||
197 | */ | ||
198 | |||
199 | #define TIPC_ERRINFO 1 /* error info */ | ||
200 | #define TIPC_RETDATA 2 /* returned data */ | ||
201 | #define TIPC_DESTNAME 3 /* destination name */ | ||
202 | |||
203 | /* | ||
204 | * TIPC-specific socket option values | ||
205 | */ | ||
206 | |||
207 | #define TIPC_IMPORTANCE 127 /* Default: TIPC_LOW_IMPORTANCE */ | ||
208 | #define TIPC_SRC_DROPPABLE 128 /* Default: 0 (resend congested msg) */ | ||
209 | #define TIPC_DEST_DROPPABLE 129 /* Default: based on socket type */ | ||
210 | #define TIPC_CONN_TIMEOUT 130 /* Default: 8000 (ms) */ | ||
211 | |||
212 | #endif | ||
diff --git a/include/linux/tipc_config.h b/include/linux/tipc_config.h new file mode 100644 index 000000000000..a52c8c64a5a3 --- /dev/null +++ b/include/linux/tipc_config.h | |||
@@ -0,0 +1,407 @@ | |||
1 | /* | ||
2 | * include/linux/tipc_config.h: Include file for TIPC configuration interface | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _LINUX_TIPC_CONFIG_H_ | ||
38 | #define _LINUX_TIPC_CONFIG_H_ | ||
39 | |||
40 | #include <linux/types.h> | ||
41 | #include <linux/string.h> | ||
42 | #include <asm/byteorder.h> | ||
43 | |||
44 | /* | ||
45 | * Configuration | ||
46 | * | ||
47 | * All configuration management messaging involves sending a request message | ||
48 | * to the TIPC configuration service on a node, which sends a reply message | ||
49 | * back. (In the future multi-message replies may be supported.) | ||
50 | * | ||
51 | * Both request and reply messages consist of a transport header and payload. | ||
52 | * The transport header contains info about the desired operation; | ||
53 | * the payload consists of zero or more type/length/value (TLV) items | ||
54 | * which specify parameters or results for the operation. | ||
55 | * | ||
56 | * For many operations, the request and reply messages have a fixed number | ||
57 | * of TLVs (usually zero or one); however, some reply messages may return | ||
58 | * a variable number of TLVs. A failed request is denoted by the presence | ||
59 | * of an "error string" TLV in the reply message instead of the TLV(s) the | ||
60 | * reply should contain if the request succeeds. | ||
61 | */ | ||
62 | |||
63 | /* | ||
64 | * Public commands: | ||
65 | * May be issued by any process. | ||
66 | * Accepted by own node, or by remote node only if remote management enabled. | ||
67 | */ | ||
68 | |||
69 | #define TIPC_CMD_NOOP 0x0000 /* tx none, rx none */ | ||
70 | #define TIPC_CMD_GET_NODES 0x0001 /* tx net_addr, rx node_info(s) */ | ||
71 | #define TIPC_CMD_GET_MEDIA_NAMES 0x0002 /* tx none, rx media_name(s) */ | ||
72 | #define TIPC_CMD_GET_BEARER_NAMES 0x0003 /* tx none, rx bearer_name(s) */ | ||
73 | #define TIPC_CMD_GET_LINKS 0x0004 /* tx net_addr, rx link_info(s) */ | ||
74 | #define TIPC_CMD_SHOW_NAME_TABLE 0x0005 /* tx name_tbl_query, rx ultra_string */ | ||
75 | #define TIPC_CMD_SHOW_PORTS 0x0006 /* tx none, rx ultra_string */ | ||
76 | #define TIPC_CMD_SHOW_LINK_STATS 0x000B /* tx link_name, rx ultra_string */ | ||
77 | |||
78 | #if 0 | ||
79 | #define TIPC_CMD_SHOW_PORT_STATS 0x0008 /* tx port_ref, rx ultra_string */ | ||
80 | #define TIPC_CMD_RESET_PORT_STATS 0x0009 /* tx port_ref, rx none */ | ||
81 | #define TIPC_CMD_GET_ROUTES 0x000A /* tx ?, rx ? */ | ||
82 | #define TIPC_CMD_GET_LINK_PEER 0x000D /* tx link_name, rx ? */ | ||
83 | #endif | ||
84 | |||
85 | /* | ||
86 | * Protected commands: | ||
87 | * May only be issued by "network administration capable" process. | ||
88 | * Accepted by own node, or by remote node only if remote management enabled | ||
89 | * and this node is zone manager. | ||
90 | */ | ||
91 | |||
92 | #define TIPC_CMD_GET_REMOTE_MNG 0x4003 /* tx none, rx unsigned */ | ||
93 | #define TIPC_CMD_GET_MAX_PORTS 0x4004 /* tx none, rx unsigned */ | ||
94 | #define TIPC_CMD_GET_MAX_PUBL 0x4005 /* tx none, rx unsigned */ | ||
95 | #define TIPC_CMD_GET_MAX_SUBSCR 0x4006 /* tx none, rx unsigned */ | ||
96 | #define TIPC_CMD_GET_MAX_ZONES 0x4007 /* tx none, rx unsigned */ | ||
97 | #define TIPC_CMD_GET_MAX_CLUSTERS 0x4008 /* tx none, rx unsigned */ | ||
98 | #define TIPC_CMD_GET_MAX_NODES 0x4009 /* tx none, rx unsigned */ | ||
99 | #define TIPC_CMD_GET_MAX_SLAVES 0x400A /* tx none, rx unsigned */ | ||
100 | #define TIPC_CMD_GET_NETID 0x400B /* tx none, rx unsigned */ | ||
101 | |||
102 | #define TIPC_CMD_ENABLE_BEARER 0x4101 /* tx bearer_config, rx none */ | ||
103 | #define TIPC_CMD_DISABLE_BEARER 0x4102 /* tx bearer_name, rx none */ | ||
104 | #define TIPC_CMD_SET_LINK_TOL 0x4107 /* tx link_config, rx none */ | ||
105 | #define TIPC_CMD_SET_LINK_PRI 0x4108 /* tx link_config, rx none */ | ||
106 | #define TIPC_CMD_SET_LINK_WINDOW 0x4109 /* tx link_config, rx none */ | ||
107 | #define TIPC_CMD_SET_LOG_SIZE 0x410A /* tx unsigned, rx none */ | ||
108 | #define TIPC_CMD_DUMP_LOG 0x410B /* tx none, rx ultra_string */ | ||
109 | #define TIPC_CMD_RESET_LINK_STATS 0x410C /* tx link_name, rx none */ | ||
110 | |||
111 | #if 0 | ||
112 | #define TIPC_CMD_CREATE_LINK 0x4103 /* tx link_create, rx none */ | ||
113 | #define TIPC_CMD_REMOVE_LINK 0x4104 /* tx link_name, rx none */ | ||
114 | #define TIPC_CMD_BLOCK_LINK 0x4105 /* tx link_name, rx none */ | ||
115 | #define TIPC_CMD_UNBLOCK_LINK 0x4106 /* tx link_name, rx none */ | ||
116 | #endif | ||
117 | |||
118 | /* | ||
119 | * Private commands: | ||
120 | * May only be issued by "network administration capable" process. | ||
121 | * Accepted by own node only; cannot be used on a remote node. | ||
122 | */ | ||
123 | |||
124 | #define TIPC_CMD_SET_NODE_ADDR 0x8001 /* tx net_addr, rx none */ | ||
125 | #if 0 | ||
126 | #define TIPC_CMD_SET_ZONE_MASTER 0x8002 /* tx none, rx none */ | ||
127 | #endif | ||
128 | #define TIPC_CMD_SET_REMOTE_MNG 0x8003 /* tx unsigned, rx none */ | ||
129 | #define TIPC_CMD_SET_MAX_PORTS 0x8004 /* tx unsigned, rx none */ | ||
130 | #define TIPC_CMD_SET_MAX_PUBL 0x8005 /* tx unsigned, rx none */ | ||
131 | #define TIPC_CMD_SET_MAX_SUBSCR 0x8006 /* tx unsigned, rx none */ | ||
132 | #define TIPC_CMD_SET_MAX_ZONES 0x8007 /* tx unsigned, rx none */ | ||
133 | #define TIPC_CMD_SET_MAX_CLUSTERS 0x8008 /* tx unsigned, rx none */ | ||
134 | #define TIPC_CMD_SET_MAX_NODES 0x8009 /* tx unsigned, rx none */ | ||
135 | #define TIPC_CMD_SET_MAX_SLAVES 0x800A /* tx unsigned, rx none */ | ||
136 | #define TIPC_CMD_SET_NETID 0x800B /* tx unsigned, rx none */ | ||
137 | |||
138 | /* | ||
139 | * TLV types defined for TIPC | ||
140 | */ | ||
141 | |||
142 | #define TIPC_TLV_NONE 0 /* no TLV present */ | ||
143 | #define TIPC_TLV_VOID 1 /* empty TLV (0 data bytes)*/ | ||
144 | #define TIPC_TLV_UNSIGNED 2 /* 32-bit integer */ | ||
145 | #define TIPC_TLV_STRING 3 /* char[128] (max) */ | ||
146 | #define TIPC_TLV_LARGE_STRING 4 /* char[2048] (max) */ | ||
147 | #define TIPC_TLV_ULTRA_STRING 5 /* char[32768] (max) */ | ||
148 | |||
149 | #define TIPC_TLV_ERROR_STRING 16 /* char[128] containing "error code" */ | ||
150 | #define TIPC_TLV_NET_ADDR 17 /* 32-bit integer denoting <Z.C.N> */ | ||
151 | #define TIPC_TLV_MEDIA_NAME 18 /* char[TIPC_MAX_MEDIA_NAME] */ | ||
152 | #define TIPC_TLV_BEARER_NAME 19 /* char[TIPC_MAX_BEARER_NAME] */ | ||
153 | #define TIPC_TLV_LINK_NAME 20 /* char[TIPC_MAX_LINK_NAME] */ | ||
154 | #define TIPC_TLV_NODE_INFO 21 /* struct tipc_node_info */ | ||
155 | #define TIPC_TLV_LINK_INFO 22 /* struct tipc_link_info */ | ||
156 | #define TIPC_TLV_BEARER_CONFIG 23 /* struct tipc_bearer_config */ | ||
157 | #define TIPC_TLV_LINK_CONFIG 24 /* struct tipc_link_config */ | ||
158 | #define TIPC_TLV_NAME_TBL_QUERY 25 /* struct tipc_name_table_query */ | ||
159 | #define TIPC_TLV_PORT_REF 26 /* 32-bit port reference */ | ||
160 | |||
161 | /* | ||
162 | * Maximum sizes of TIPC bearer-related names (including terminating NUL) | ||
163 | */ | ||
164 | |||
165 | #define TIPC_MAX_MEDIA_NAME 16 /* format = media */ | ||
166 | #define TIPC_MAX_IF_NAME 16 /* format = interface */ | ||
167 | #define TIPC_MAX_BEARER_NAME 32 /* format = media:interface */ | ||
168 | #define TIPC_MAX_LINK_NAME 60 /* format = Z.C.N:interface-Z.C.N:interface */ | ||
169 | |||
170 | /* | ||
171 | * Link priority limits (range from 0 to # priorities - 1) | ||
172 | */ | ||
173 | |||
174 | #define TIPC_NUM_LINK_PRI 32 | ||
175 | |||
176 | /* | ||
177 | * Link tolerance limits (min, default, max), in ms | ||
178 | */ | ||
179 | |||
180 | #define TIPC_MIN_LINK_TOL 50 | ||
181 | #define TIPC_DEF_LINK_TOL 1500 | ||
182 | #define TIPC_MAX_LINK_TOL 30000 | ||
183 | |||
184 | /* | ||
185 | * Link window limits (min, default, max), in packets | ||
186 | */ | ||
187 | |||
188 | #define TIPC_MIN_LINK_WIN 16 | ||
189 | #define TIPC_DEF_LINK_WIN 50 | ||
190 | #define TIPC_MAX_LINK_WIN 150 | ||
191 | |||
192 | |||
193 | struct tipc_node_info { | ||
194 | __u32 addr; /* network address of node */ | ||
195 | __u32 up; /* 0=down, 1= up */ | ||
196 | }; | ||
197 | |||
198 | struct tipc_link_info { | ||
199 | __u32 dest; /* network address of peer node */ | ||
200 | __u32 up; /* 0=down, 1=up */ | ||
201 | char str[TIPC_MAX_LINK_NAME]; /* link name */ | ||
202 | }; | ||
203 | |||
204 | struct tipc_bearer_config { | ||
205 | __u32 priority; /* Range [1,31]. Override per link */ | ||
206 | __u32 detect_scope; | ||
207 | char name[TIPC_MAX_BEARER_NAME]; | ||
208 | }; | ||
209 | |||
210 | struct tipc_link_config { | ||
211 | __u32 value; | ||
212 | char name[TIPC_MAX_LINK_NAME]; | ||
213 | }; | ||
214 | |||
215 | #define TIPC_NTQ_ALLTYPES 0x80000000 | ||
216 | |||
217 | struct tipc_name_table_query { | ||
218 | __u32 depth; /* 1:type, 2:+name info, 3:+port info, 4+:+debug info */ | ||
219 | __u32 type; /* {t,l,u} info ignored if high bit of "depth" is set */ | ||
220 | __u32 lowbound; /* (i.e. displays all entries of name table) */ | ||
221 | __u32 upbound; | ||
222 | }; | ||
223 | |||
224 | /* | ||
225 | * The error string TLV is a null-terminated string describing the cause | ||
226 | * of the request failure. To simplify error processing (and to save space) | ||
227 | * the first character of the string can be a special error code character | ||
228 | * (lying by the range 0x80 to 0xFF) which represents a pre-defined reason. | ||
229 | */ | ||
230 | |||
231 | #define TIPC_CFG_TLV_ERROR "\x80" /* request contains incorrect TLV(s) */ | ||
232 | #define TIPC_CFG_NOT_NET_ADMIN "\x81" /* must be network administrator */ | ||
233 | #define TIPC_CFG_NOT_ZONE_MSTR "\x82" /* must be zone master */ | ||
234 | #define TIPC_CFG_NO_REMOTE "\x83" /* remote management not enabled */ | ||
235 | #define TIPC_CFG_NOT_SUPPORTED "\x84" /* request is not supported by TIPC */ | ||
236 | #define TIPC_CFG_INVALID_VALUE "\x85" /* request has invalid argument value */ | ||
237 | |||
238 | #if 0 | ||
239 | /* prototypes TLV structures for proposed commands */ | ||
240 | struct tipc_link_create { | ||
241 | __u32 domain; | ||
242 | struct tipc_media_addr peer_addr; | ||
243 | char bearer_name[TIPC_MAX_BEARER_NAME]; | ||
244 | }; | ||
245 | |||
246 | struct tipc_route_info { | ||
247 | __u32 dest; | ||
248 | __u32 router; | ||
249 | }; | ||
250 | #endif | ||
251 | |||
252 | /* | ||
253 | * A TLV consists of a descriptor, followed by the TLV value. | ||
254 | * TLV descriptor fields are stored in network byte order; | ||
255 | * TLV values must also be stored in network byte order (where applicable). | ||
256 | * TLV descriptors must be aligned to addresses which are multiple of 4, | ||
257 | * so up to 3 bytes of padding may exist at the end of the TLV value area. | ||
258 | * There must not be any padding between the TLV descriptor and its value. | ||
259 | */ | ||
260 | |||
261 | struct tlv_desc { | ||
262 | __u16 tlv_len; /* TLV length (descriptor + value) */ | ||
263 | __u16 tlv_type; /* TLV identifier */ | ||
264 | }; | ||
265 | |||
266 | #define TLV_ALIGNTO 4 | ||
267 | |||
268 | #define TLV_ALIGN(datalen) (((datalen)+(TLV_ALIGNTO-1)) & ~(TLV_ALIGNTO-1)) | ||
269 | #define TLV_LENGTH(datalen) (sizeof(struct tlv_desc) + (datalen)) | ||
270 | #define TLV_SPACE(datalen) (TLV_ALIGN(TLV_LENGTH(datalen))) | ||
271 | #define TLV_DATA(tlv) ((void *)((char *)(tlv) + TLV_LENGTH(0))) | ||
272 | |||
273 | static inline int TLV_OK(const void *tlv, __u16 space) | ||
274 | { | ||
275 | /* | ||
276 | * Would also like to check that "tlv" is a multiple of 4, | ||
277 | * but don't know how to do this in a portable way. | ||
278 | * - Tried doing (!(tlv & (TLV_ALIGNTO-1))), but GCC compiler | ||
279 | * won't allow binary "&" with a pointer. | ||
280 | * - Tried casting "tlv" to integer type, but causes warning about size | ||
281 | * mismatch when pointer is bigger than chosen type (int, long, ...). | ||
282 | */ | ||
283 | |||
284 | return (space >= TLV_SPACE(0)) && | ||
285 | (ntohs(((struct tlv_desc *)tlv)->tlv_len) <= space); | ||
286 | } | ||
287 | |||
288 | static inline int TLV_CHECK(const void *tlv, __u16 space, __u16 exp_type) | ||
289 | { | ||
290 | return TLV_OK(tlv, space) && | ||
291 | (ntohs(((struct tlv_desc *)tlv)->tlv_type) == exp_type); | ||
292 | } | ||
293 | |||
294 | static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len) | ||
295 | { | ||
296 | struct tlv_desc *tlv_ptr; | ||
297 | int tlv_len; | ||
298 | |||
299 | tlv_len = TLV_LENGTH(len); | ||
300 | tlv_ptr = (struct tlv_desc *)tlv; | ||
301 | tlv_ptr->tlv_type = htons(type); | ||
302 | tlv_ptr->tlv_len = htons(tlv_len); | ||
303 | if (len && data) | ||
304 | memcpy(TLV_DATA(tlv_ptr), data, tlv_len); | ||
305 | return TLV_SPACE(len); | ||
306 | } | ||
307 | |||
308 | /* | ||
309 | * A TLV list descriptor simplifies processing of messages | ||
310 | * containing multiple TLVs. | ||
311 | */ | ||
312 | |||
313 | struct tlv_list_desc { | ||
314 | struct tlv_desc *tlv_ptr; /* ptr to current TLV */ | ||
315 | __u32 tlv_space; /* # bytes from curr TLV to list end */ | ||
316 | }; | ||
317 | |||
318 | static inline void TLV_LIST_INIT(struct tlv_list_desc *list, | ||
319 | void *data, __u32 space) | ||
320 | { | ||
321 | list->tlv_ptr = (struct tlv_desc *)data; | ||
322 | list->tlv_space = space; | ||
323 | } | ||
324 | |||
325 | static inline int TLV_LIST_EMPTY(struct tlv_list_desc *list) | ||
326 | { | ||
327 | return (list->tlv_space == 0); | ||
328 | } | ||
329 | |||
330 | static inline int TLV_LIST_CHECK(struct tlv_list_desc *list, __u16 exp_type) | ||
331 | { | ||
332 | return TLV_CHECK(list->tlv_ptr, list->tlv_space, exp_type); | ||
333 | } | ||
334 | |||
335 | static inline void *TLV_LIST_DATA(struct tlv_list_desc *list) | ||
336 | { | ||
337 | return TLV_DATA(list->tlv_ptr); | ||
338 | } | ||
339 | |||
340 | static inline void TLV_LIST_STEP(struct tlv_list_desc *list) | ||
341 | { | ||
342 | __u16 tlv_space = TLV_ALIGN(ntohs(list->tlv_ptr->tlv_len)); | ||
343 | |||
344 | list->tlv_ptr = (struct tlv_desc *)((char *)list->tlv_ptr + tlv_space); | ||
345 | list->tlv_space -= tlv_space; | ||
346 | } | ||
347 | |||
348 | /* | ||
349 | * Configuration messages exchanged via NETLINK_GENERIC use the following | ||
350 | * family id, name, version and command. | ||
351 | */ | ||
352 | #define TIPC_GENL_NAME "TIPC" | ||
353 | #define TIPC_GENL_VERSION 0x1 | ||
354 | #define TIPC_GENL_CMD 0x1 | ||
355 | |||
356 | /* | ||
357 | * TIPC specific header used in NETLINK_GENERIC requests. | ||
358 | */ | ||
359 | struct tipc_genlmsghdr { | ||
360 | __u32 dest; /* Destination address */ | ||
361 | __u16 cmd; /* Command */ | ||
362 | __u16 reserved; /* Unused */ | ||
363 | }; | ||
364 | |||
365 | #define TIPC_GENL_HDRLEN NLMSG_ALIGN(sizeof(struct tipc_genlmsghdr)) | ||
366 | |||
367 | /* | ||
368 | * Configuration messages exchanged via TIPC sockets use the TIPC configuration | ||
369 | * message header, which is defined below. This structure is analogous | ||
370 | * to the Netlink message header, but fields are stored in network byte order | ||
371 | * and no padding is permitted between the header and the message data | ||
372 | * that follows. | ||
373 | */ | ||
374 | |||
375 | struct tipc_cfg_msg_hdr | ||
376 | { | ||
377 | __u32 tcm_len; /* Message length (including header) */ | ||
378 | __u16 tcm_type; /* Command type */ | ||
379 | __u16 tcm_flags; /* Additional flags */ | ||
380 | char tcm_reserved[8]; /* Unused */ | ||
381 | }; | ||
382 | |||
383 | #define TCM_F_REQUEST 0x1 /* Flag: Request message */ | ||
384 | #define TCM_F_MORE 0x2 /* Flag: Message to be continued */ | ||
385 | |||
386 | #define TCM_ALIGN(datalen) (((datalen)+3) & ~3) | ||
387 | #define TCM_LENGTH(datalen) (sizeof(struct tipc_cfg_msg_hdr) + datalen) | ||
388 | #define TCM_SPACE(datalen) (TCM_ALIGN(TCM_LENGTH(datalen))) | ||
389 | #define TCM_DATA(tcm_hdr) ((void *)((char *)(tcm_hdr) + TCM_LENGTH(0))) | ||
390 | |||
391 | static inline int TCM_SET(void *msg, __u16 cmd, __u16 flags, | ||
392 | void *data, __u16 data_len) | ||
393 | { | ||
394 | struct tipc_cfg_msg_hdr *tcm_hdr; | ||
395 | int msg_len; | ||
396 | |||
397 | msg_len = TCM_LENGTH(data_len); | ||
398 | tcm_hdr = (struct tipc_cfg_msg_hdr *)msg; | ||
399 | tcm_hdr->tcm_len = htonl(msg_len); | ||
400 | tcm_hdr->tcm_type = htons(cmd); | ||
401 | tcm_hdr->tcm_flags = htons(flags); | ||
402 | if (data_len && data) | ||
403 | memcpy(TCM_DATA(msg), data, data_len); | ||
404 | return TCM_SPACE(data_len); | ||
405 | } | ||
406 | |||
407 | #endif | ||
diff --git a/include/net/genetlink.h b/include/net/genetlink.h index c5b96b2b8155..805de50df00d 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h | |||
@@ -22,7 +22,6 @@ struct genl_family | |||
22 | char name[GENL_NAMSIZ]; | 22 | char name[GENL_NAMSIZ]; |
23 | unsigned int version; | 23 | unsigned int version; |
24 | unsigned int maxattr; | 24 | unsigned int maxattr; |
25 | struct module * owner; | ||
26 | struct nlattr ** attrbuf; /* private */ | 25 | struct nlattr ** attrbuf; /* private */ |
27 | struct list_head ops_list; /* private */ | 26 | struct list_head ops_list; /* private */ |
28 | struct list_head family_list; /* private */ | 27 | struct list_head family_list; /* private */ |
diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h index 25b081a730e6..91684436af8e 100644 --- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h +++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h | |||
@@ -37,7 +37,4 @@ struct nf_conntrack_ipv4 { | |||
37 | struct sk_buff * | 37 | struct sk_buff * |
38 | nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb); | 38 | nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb); |
39 | 39 | ||
40 | /* call to create an explicit dependency on nf_conntrack_l3proto_ipv4. */ | ||
41 | extern void need_ip_conntrack(void); | ||
42 | |||
43 | #endif /*_NF_CONNTRACK_IPV4_H*/ | 40 | #endif /*_NF_CONNTRACK_IPV4_H*/ |
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 64b82b74a650..6d075ca16e6e 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h | |||
@@ -221,9 +221,6 @@ extern void nf_ct_helper_put(struct nf_conntrack_helper *helper); | |||
221 | extern struct nf_conntrack_helper * | 221 | extern struct nf_conntrack_helper * |
222 | __nf_conntrack_helper_find_byname(const char *name); | 222 | __nf_conntrack_helper_find_byname(const char *name); |
223 | 223 | ||
224 | /* call to create an explicit dependency on nf_conntrack. */ | ||
225 | extern void need_nf_conntrack(void); | ||
226 | |||
227 | extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, | 224 | extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, |
228 | const struct nf_conntrack_tuple *orig); | 225 | const struct nf_conntrack_tuple *orig); |
229 | 226 | ||
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h index 14ce790e5c65..530ef1f75283 100644 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ b/include/net/netfilter/nf_conntrack_tuple.h | |||
@@ -111,7 +111,7 @@ struct nf_conntrack_tuple | |||
111 | #ifdef __KERNEL__ | 111 | #ifdef __KERNEL__ |
112 | 112 | ||
113 | #define NF_CT_DUMP_TUPLE(tp) \ | 113 | #define NF_CT_DUMP_TUPLE(tp) \ |
114 | DEBUGP("tuple %p: %u %u %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu -> %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu\n", \ | 114 | DEBUGP("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n", \ |
115 | (tp), (tp)->src.l3num, (tp)->dst.protonum, \ | 115 | (tp), (tp)->src.l3num, (tp)->dst.protonum, \ |
116 | NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \ | 116 | NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \ |
117 | NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all)) | 117 | NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all)) |
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 8f241216f46b..a553f39f6aee 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h | |||
@@ -225,13 +225,13 @@ extern int sctp_debug_flag; | |||
225 | if (sctp_debug_flag) { \ | 225 | if (sctp_debug_flag) { \ |
226 | if (saddr->sa.sa_family == AF_INET6) { \ | 226 | if (saddr->sa.sa_family == AF_INET6) { \ |
227 | printk(KERN_DEBUG \ | 227 | printk(KERN_DEBUG \ |
228 | lead "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" trail, \ | 228 | lead NIP6_FMT trail, \ |
229 | leadparm, \ | 229 | leadparm, \ |
230 | NIP6(saddr->v6.sin6_addr), \ | 230 | NIP6(saddr->v6.sin6_addr), \ |
231 | otherparms); \ | 231 | otherparms); \ |
232 | } else { \ | 232 | } else { \ |
233 | printk(KERN_DEBUG \ | 233 | printk(KERN_DEBUG \ |
234 | lead "%u.%u.%u.%u" trail, \ | 234 | lead NIPQUAD_FMT trail, \ |
235 | leadparm, \ | 235 | leadparm, \ |
236 | NIPQUAD(saddr->v4.sin_addr.s_addr), \ | 236 | NIPQUAD(saddr->v4.sin_addr.s_addr), \ |
237 | otherparms); \ | 237 | otherparms); \ |
diff --git a/include/net/tipc/tipc.h b/include/net/tipc/tipc.h new file mode 100644 index 000000000000..9566608c88cf --- /dev/null +++ b/include/net/tipc/tipc.h | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | * include/net/tipc/tipc.h: Main include file for TIPC users | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _NET_TIPC_H_ | ||
38 | #define _NET_TIPC_H_ | ||
39 | |||
40 | #ifdef __KERNEL__ | ||
41 | |||
42 | #include <linux/tipc.h> | ||
43 | #include <linux/skbuff.h> | ||
44 | |||
45 | /* | ||
46 | * Native API | ||
47 | */ | ||
48 | |||
49 | /* | ||
50 | * TIPC operating mode routines | ||
51 | */ | ||
52 | |||
53 | u32 tipc_get_addr(void); | ||
54 | |||
55 | #define TIPC_NOT_RUNNING 0 | ||
56 | #define TIPC_NODE_MODE 1 | ||
57 | #define TIPC_NET_MODE 2 | ||
58 | |||
59 | typedef void (*tipc_mode_event)(void *usr_handle, int mode, u32 addr); | ||
60 | |||
61 | int tipc_attach(unsigned int *userref, tipc_mode_event, void *usr_handle); | ||
62 | |||
63 | void tipc_detach(unsigned int userref); | ||
64 | |||
65 | int tipc_get_mode(void); | ||
66 | |||
67 | /* | ||
68 | * TIPC port manipulation routines | ||
69 | */ | ||
70 | |||
71 | typedef void (*tipc_msg_err_event) (void *usr_handle, | ||
72 | u32 portref, | ||
73 | struct sk_buff **buf, | ||
74 | unsigned char const *data, | ||
75 | unsigned int size, | ||
76 | int reason, | ||
77 | struct tipc_portid const *attmpt_destid); | ||
78 | |||
79 | typedef void (*tipc_named_msg_err_event) (void *usr_handle, | ||
80 | u32 portref, | ||
81 | struct sk_buff **buf, | ||
82 | unsigned char const *data, | ||
83 | unsigned int size, | ||
84 | int reason, | ||
85 | struct tipc_name_seq const *attmpt_dest); | ||
86 | |||
87 | typedef void (*tipc_conn_shutdown_event) (void *usr_handle, | ||
88 | u32 portref, | ||
89 | struct sk_buff **buf, | ||
90 | unsigned char const *data, | ||
91 | unsigned int size, | ||
92 | int reason); | ||
93 | |||
94 | typedef void (*tipc_msg_event) (void *usr_handle, | ||
95 | u32 portref, | ||
96 | struct sk_buff **buf, | ||
97 | unsigned char const *data, | ||
98 | unsigned int size, | ||
99 | unsigned int importance, | ||
100 | struct tipc_portid const *origin); | ||
101 | |||
102 | typedef void (*tipc_named_msg_event) (void *usr_handle, | ||
103 | u32 portref, | ||
104 | struct sk_buff **buf, | ||
105 | unsigned char const *data, | ||
106 | unsigned int size, | ||
107 | unsigned int importance, | ||
108 | struct tipc_portid const *orig, | ||
109 | struct tipc_name_seq const *dest); | ||
110 | |||
111 | typedef void (*tipc_conn_msg_event) (void *usr_handle, | ||
112 | u32 portref, | ||
113 | struct sk_buff **buf, | ||
114 | unsigned char const *data, | ||
115 | unsigned int size); | ||
116 | |||
117 | typedef void (*tipc_continue_event) (void *usr_handle, | ||
118 | u32 portref); | ||
119 | |||
120 | int tipc_createport(unsigned int tipc_user, | ||
121 | void *usr_handle, | ||
122 | unsigned int importance, | ||
123 | tipc_msg_err_event error_cb, | ||
124 | tipc_named_msg_err_event named_error_cb, | ||
125 | tipc_conn_shutdown_event conn_error_cb, | ||
126 | tipc_msg_event message_cb, | ||
127 | tipc_named_msg_event named_message_cb, | ||
128 | tipc_conn_msg_event conn_message_cb, | ||
129 | tipc_continue_event continue_event_cb,/* May be zero */ | ||
130 | u32 *portref); | ||
131 | |||
132 | int tipc_deleteport(u32 portref); | ||
133 | |||
134 | int tipc_ownidentity(u32 portref, struct tipc_portid *port); | ||
135 | |||
136 | int tipc_portimportance(u32 portref, unsigned int *importance); | ||
137 | int tipc_set_portimportance(u32 portref, unsigned int importance); | ||
138 | |||
139 | int tipc_portunreliable(u32 portref, unsigned int *isunreliable); | ||
140 | int tipc_set_portunreliable(u32 portref, unsigned int isunreliable); | ||
141 | |||
142 | int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable); | ||
143 | int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable); | ||
144 | |||
145 | int tipc_publish(u32 portref, unsigned int scope, | ||
146 | struct tipc_name_seq const *name_seq); | ||
147 | int tipc_withdraw(u32 portref, unsigned int scope, | ||
148 | struct tipc_name_seq const *name_seq); /* 0: all */ | ||
149 | |||
150 | int tipc_connect2port(u32 portref, struct tipc_portid const *port); | ||
151 | |||
152 | int tipc_disconnect(u32 portref); | ||
153 | |||
154 | int tipc_shutdown(u32 ref); /* Sends SHUTDOWN msg */ | ||
155 | |||
156 | int tipc_isconnected(u32 portref, int *isconnected); | ||
157 | |||
158 | int tipc_peer(u32 portref, struct tipc_portid *peer); | ||
159 | |||
160 | int tipc_ref_valid(u32 portref); | ||
161 | |||
162 | /* | ||
163 | * TIPC messaging routines | ||
164 | */ | ||
165 | |||
166 | #define TIPC_PORT_IMPORTANCE 100 /* send using current port setting */ | ||
167 | |||
168 | |||
169 | int tipc_send(u32 portref, | ||
170 | unsigned int num_sect, | ||
171 | struct iovec const *msg_sect); | ||
172 | |||
173 | int tipc_send_buf(u32 portref, | ||
174 | struct sk_buff *buf, | ||
175 | unsigned int dsz); | ||
176 | |||
177 | int tipc_send2name(u32 portref, | ||
178 | struct tipc_name const *name, | ||
179 | u32 domain, /* 0:own zone */ | ||
180 | unsigned int num_sect, | ||
181 | struct iovec const *msg_sect); | ||
182 | |||
183 | int tipc_send_buf2name(u32 portref, | ||
184 | struct tipc_name const *name, | ||
185 | u32 domain, | ||
186 | struct sk_buff *buf, | ||
187 | unsigned int dsz); | ||
188 | |||
189 | int tipc_forward2name(u32 portref, | ||
190 | struct tipc_name const *name, | ||
191 | u32 domain, /*0: own zone */ | ||
192 | unsigned int section_count, | ||
193 | struct iovec const *msg_sect, | ||
194 | struct tipc_portid const *origin, | ||
195 | unsigned int importance); | ||
196 | |||
197 | int tipc_forward_buf2name(u32 portref, | ||
198 | struct tipc_name const *name, | ||
199 | u32 domain, | ||
200 | struct sk_buff *buf, | ||
201 | unsigned int dsz, | ||
202 | struct tipc_portid const *orig, | ||
203 | unsigned int importance); | ||
204 | |||
205 | int tipc_send2port(u32 portref, | ||
206 | struct tipc_portid const *dest, | ||
207 | unsigned int num_sect, | ||
208 | struct iovec const *msg_sect); | ||
209 | |||
210 | int tipc_send_buf2port(u32 portref, | ||
211 | struct tipc_portid const *dest, | ||
212 | struct sk_buff *buf, | ||
213 | unsigned int dsz); | ||
214 | |||
215 | int tipc_forward2port(u32 portref, | ||
216 | struct tipc_portid const *dest, | ||
217 | unsigned int num_sect, | ||
218 | struct iovec const *msg_sect, | ||
219 | struct tipc_portid const *origin, | ||
220 | unsigned int importance); | ||
221 | |||
222 | int tipc_forward_buf2port(u32 portref, | ||
223 | struct tipc_portid const *dest, | ||
224 | struct sk_buff *buf, | ||
225 | unsigned int dsz, | ||
226 | struct tipc_portid const *orig, | ||
227 | unsigned int importance); | ||
228 | |||
229 | int tipc_multicast(u32 portref, | ||
230 | struct tipc_name_seq const *seq, | ||
231 | u32 domain, /* 0:own zone */ | ||
232 | unsigned int section_count, | ||
233 | struct iovec const *msg); | ||
234 | |||
235 | #if 0 | ||
236 | int tipc_multicast_buf(u32 portref, | ||
237 | struct tipc_name_seq const *seq, | ||
238 | u32 domain, /* 0:own zone */ | ||
239 | void *buf, | ||
240 | unsigned int size); | ||
241 | #endif | ||
242 | |||
243 | /* | ||
244 | * TIPC subscription routines | ||
245 | */ | ||
246 | |||
247 | int tipc_ispublished(struct tipc_name const *name); | ||
248 | |||
249 | /* | ||
250 | * Get number of available nodes within specified domain (excluding own node) | ||
251 | */ | ||
252 | |||
253 | unsigned int tipc_available_nodes(const u32 domain); | ||
254 | |||
255 | #endif | ||
256 | |||
257 | #endif | ||
diff --git a/include/net/tipc/tipc_bearer.h b/include/net/tipc/tipc_bearer.h new file mode 100644 index 000000000000..098607cd4b78 --- /dev/null +++ b/include/net/tipc/tipc_bearer.h | |||
@@ -0,0 +1,121 @@ | |||
1 | /* | ||
2 | * include/net/tipc/tipc_bearer.h: Include file for privileged access to TIPC bearers | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _NET_TIPC_BEARER_H_ | ||
38 | #define _NET_TIPC_BEARER_H_ | ||
39 | |||
40 | #ifdef __KERNEL__ | ||
41 | |||
42 | #include <linux/tipc_config.h> | ||
43 | #include <linux/skbuff.h> | ||
44 | #include <linux/spinlock.h> | ||
45 | |||
46 | /* | ||
47 | * Identifiers of supported TIPC media types | ||
48 | */ | ||
49 | |||
50 | #define TIPC_MEDIA_TYPE_ETH 1 | ||
51 | |||
52 | struct tipc_media_addr { | ||
53 | __u32 type; | ||
54 | union { | ||
55 | __u8 eth_addr[6]; /* Ethernet bearer */ | ||
56 | #if 0 | ||
57 | /* Prototypes for other possible bearer types */ | ||
58 | |||
59 | struct { | ||
60 | __u16 sin_family; | ||
61 | __u16 sin_port; | ||
62 | struct { | ||
63 | __u32 s_addr; | ||
64 | } sin_addr; | ||
65 | char pad[4]; | ||
66 | } addr_in; /* IP-based bearer */ | ||
67 | __u16 sock_descr; /* generic socket bearer */ | ||
68 | #endif | ||
69 | } dev_addr; | ||
70 | }; | ||
71 | |||
72 | /** | ||
73 | * struct tipc_bearer - TIPC bearer info available to privileged users | ||
74 | * @usr_handle: pointer to additional user-defined information about bearer | ||
75 | * @mtu: max packet size bearer can support | ||
76 | * @blocked: non-zero if bearer is blocked | ||
77 | * @lock: spinlock for controlling access to bearer | ||
78 | * @addr: media-specific address associated with bearer | ||
79 | * @name: bearer name (format = media:interface) | ||
80 | * | ||
81 | * Note: TIPC initializes "name" and "lock" fields; user is responsible for | ||
82 | * initialization all other fields when a bearer is enabled. | ||
83 | */ | ||
84 | |||
85 | struct tipc_bearer { | ||
86 | void *usr_handle; | ||
87 | u32 mtu; | ||
88 | int blocked; | ||
89 | spinlock_t lock; | ||
90 | struct tipc_media_addr addr; | ||
91 | char name[TIPC_MAX_BEARER_NAME]; | ||
92 | }; | ||
93 | |||
94 | |||
95 | int tipc_register_media(u32 media_type, | ||
96 | char *media_name, | ||
97 | int (*enable)(struct tipc_bearer *), | ||
98 | void (*disable)(struct tipc_bearer *), | ||
99 | int (*send_msg)(struct sk_buff *, | ||
100 | struct tipc_bearer *, | ||
101 | struct tipc_media_addr *), | ||
102 | char *(*addr2str)(struct tipc_media_addr *a, | ||
103 | char *str_buf, | ||
104 | int str_size), | ||
105 | struct tipc_media_addr *bcast_addr, | ||
106 | const u32 bearer_priority, | ||
107 | const u32 link_tolerance, /* [ms] */ | ||
108 | const u32 send_window_limit); | ||
109 | |||
110 | void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr); | ||
111 | |||
112 | int tipc_block_bearer(const char *name); | ||
113 | void tipc_continue(struct tipc_bearer *tb_ptr); | ||
114 | |||
115 | int tipc_enable_bearer(const char *bearer_name, u32 bcast_scope, u32 priority); | ||
116 | int tipc_disable_bearer(const char *name); | ||
117 | |||
118 | |||
119 | #endif | ||
120 | |||
121 | #endif | ||
diff --git a/include/net/tipc/tipc_msg.h b/include/net/tipc/tipc_msg.h new file mode 100644 index 000000000000..4d096eebc93f --- /dev/null +++ b/include/net/tipc/tipc_msg.h | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * include/net/tipc/tipc_msg.h: Include file for privileged access to TIPC message headers | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _NET_TIPC_MSG_H_ | ||
38 | #define _NET_TIPC_MSG_H_ | ||
39 | |||
40 | #ifdef __KERNEL__ | ||
41 | |||
42 | struct tipc_msg { | ||
43 | u32 hdr[15]; | ||
44 | }; | ||
45 | |||
46 | |||
47 | /* | ||
48 | TIPC user data message header format, version 2: | ||
49 | |||
50 | |||
51 | 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0 | ||
52 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
53 | w0:|vers | user |hdr sz |n|d|s|-| message size | | ||
54 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
55 | w1:|mstyp| error |rer cnt|lsc|opt p| broadcast ack no | | ||
56 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
57 | w2:| link level ack no | broadcast/link level seq no | | ||
58 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
59 | w3:| previous node | | ||
60 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
61 | w4:| originating port | | ||
62 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
63 | w5:| destination port | | ||
64 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
65 | w6:| originating node | | ||
66 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
67 | w7:| destination node | | ||
68 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
69 | w8:| name type / transport sequence number | | ||
70 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
71 | w9:| name instance/multicast lower bound | | ||
72 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
73 | wA:| multicast upper bound | | ||
74 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
75 | / / | ||
76 | \ options \ | ||
77 | / / | ||
78 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
79 | |||
80 | */ | ||
81 | |||
82 | #define TIPC_CONN_MSG 0 | ||
83 | #define TIPC_MCAST_MSG 1 | ||
84 | #define TIPC_NAMED_MSG 2 | ||
85 | #define TIPC_DIRECT_MSG 3 | ||
86 | |||
87 | |||
88 | static inline u32 msg_word(struct tipc_msg *m, u32 pos) | ||
89 | { | ||
90 | return ntohl(m->hdr[pos]); | ||
91 | } | ||
92 | |||
93 | static inline u32 msg_bits(struct tipc_msg *m, u32 w, u32 pos, u32 mask) | ||
94 | { | ||
95 | return (msg_word(m, w) >> pos) & mask; | ||
96 | } | ||
97 | |||
98 | static inline u32 msg_importance(struct tipc_msg *m) | ||
99 | { | ||
100 | return msg_bits(m, 0, 25, 0xf); | ||
101 | } | ||
102 | |||
103 | static inline u32 msg_hdr_sz(struct tipc_msg *m) | ||
104 | { | ||
105 | return msg_bits(m, 0, 21, 0xf) << 2; | ||
106 | } | ||
107 | |||
108 | static inline int msg_short(struct tipc_msg *m) | ||
109 | { | ||
110 | return (msg_hdr_sz(m) == 24); | ||
111 | } | ||
112 | |||
113 | static inline u32 msg_size(struct tipc_msg *m) | ||
114 | { | ||
115 | return msg_bits(m, 0, 0, 0x1ffff); | ||
116 | } | ||
117 | |||
118 | static inline u32 msg_data_sz(struct tipc_msg *m) | ||
119 | { | ||
120 | return (msg_size(m) - msg_hdr_sz(m)); | ||
121 | } | ||
122 | |||
123 | static inline unchar *msg_data(struct tipc_msg *m) | ||
124 | { | ||
125 | return ((unchar *)m) + msg_hdr_sz(m); | ||
126 | } | ||
127 | |||
128 | static inline u32 msg_type(struct tipc_msg *m) | ||
129 | { | ||
130 | return msg_bits(m, 1, 29, 0x7); | ||
131 | } | ||
132 | |||
133 | static inline u32 msg_direct(struct tipc_msg *m) | ||
134 | { | ||
135 | return (msg_type(m) == TIPC_DIRECT_MSG); | ||
136 | } | ||
137 | |||
138 | static inline u32 msg_named(struct tipc_msg *m) | ||
139 | { | ||
140 | return (msg_type(m) == TIPC_NAMED_MSG); | ||
141 | } | ||
142 | |||
143 | static inline u32 msg_mcast(struct tipc_msg *m) | ||
144 | { | ||
145 | return (msg_type(m) == TIPC_MCAST_MSG); | ||
146 | } | ||
147 | |||
148 | static inline u32 msg_connected(struct tipc_msg *m) | ||
149 | { | ||
150 | return (msg_type(m) == TIPC_CONN_MSG); | ||
151 | } | ||
152 | |||
153 | static inline u32 msg_errcode(struct tipc_msg *m) | ||
154 | { | ||
155 | return msg_bits(m, 1, 25, 0xf); | ||
156 | } | ||
157 | |||
158 | static inline u32 msg_prevnode(struct tipc_msg *m) | ||
159 | { | ||
160 | return msg_word(m, 3); | ||
161 | } | ||
162 | |||
163 | static inline u32 msg_origport(struct tipc_msg *m) | ||
164 | { | ||
165 | return msg_word(m, 4); | ||
166 | } | ||
167 | |||
168 | static inline u32 msg_destport(struct tipc_msg *m) | ||
169 | { | ||
170 | return msg_word(m, 5); | ||
171 | } | ||
172 | |||
173 | static inline u32 msg_mc_netid(struct tipc_msg *m) | ||
174 | { | ||
175 | return msg_word(m, 5); | ||
176 | } | ||
177 | |||
178 | static inline u32 msg_orignode(struct tipc_msg *m) | ||
179 | { | ||
180 | if (likely(msg_short(m))) | ||
181 | return msg_prevnode(m); | ||
182 | return msg_word(m, 6); | ||
183 | } | ||
184 | |||
185 | static inline u32 msg_destnode(struct tipc_msg *m) | ||
186 | { | ||
187 | return msg_word(m, 7); | ||
188 | } | ||
189 | |||
190 | static inline u32 msg_nametype(struct tipc_msg *m) | ||
191 | { | ||
192 | return msg_word(m, 8); | ||
193 | } | ||
194 | |||
195 | static inline u32 msg_nameinst(struct tipc_msg *m) | ||
196 | { | ||
197 | return msg_word(m, 9); | ||
198 | } | ||
199 | |||
200 | static inline u32 msg_namelower(struct tipc_msg *m) | ||
201 | { | ||
202 | return msg_nameinst(m); | ||
203 | } | ||
204 | |||
205 | static inline u32 msg_nameupper(struct tipc_msg *m) | ||
206 | { | ||
207 | return msg_word(m, 10); | ||
208 | } | ||
209 | |||
210 | static inline char *msg_options(struct tipc_msg *m, u32 *len) | ||
211 | { | ||
212 | u32 pos = msg_bits(m, 1, 16, 0x7); | ||
213 | |||
214 | if (!pos) | ||
215 | return 0; | ||
216 | pos = (pos * 4) + 28; | ||
217 | *len = msg_hdr_sz(m) - pos; | ||
218 | return (char *)&m->hdr[pos/4]; | ||
219 | } | ||
220 | |||
221 | #endif | ||
222 | |||
223 | #endif | ||
diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h new file mode 100644 index 000000000000..333bba6dc522 --- /dev/null +++ b/include/net/tipc/tipc_port.h | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * include/net/tipc/tipc_port.h: Include file for privileged access to TIPC ports | ||
3 | * | ||
4 | * Copyright (c) 1994-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _NET_TIPC_PORT_H_ | ||
38 | #define _NET_TIPC_PORT_H_ | ||
39 | |||
40 | #ifdef __KERNEL__ | ||
41 | |||
42 | #include <linux/tipc.h> | ||
43 | #include <linux/skbuff.h> | ||
44 | #include <net/tipc/tipc_msg.h> | ||
45 | |||
46 | #define TIPC_FLOW_CONTROL_WIN 512 | ||
47 | |||
48 | /** | ||
49 | * struct tipc_port - native TIPC port info available to privileged users | ||
50 | * @usr_handle: pointer to additional user-defined information about port | ||
51 | * @lock: pointer to spinlock for controlling access to port | ||
52 | * @connected: non-zero if port is currently connected to a peer port | ||
53 | * @conn_type: TIPC type used when connection was established | ||
54 | * @conn_instance: TIPC instance used when connection was established | ||
55 | * @conn_unacked: number of unacknowledged messages received from peer port | ||
56 | * @published: non-zero if port has one or more associated names | ||
57 | * @congested: non-zero if cannot send because of link or port congestion | ||
58 | * @ref: unique reference to port in TIPC object registry | ||
59 | * @phdr: preformatted message header used when sending messages | ||
60 | */ | ||
61 | |||
62 | struct tipc_port { | ||
63 | void *usr_handle; | ||
64 | spinlock_t *lock; | ||
65 | int connected; | ||
66 | u32 conn_type; | ||
67 | u32 conn_instance; | ||
68 | u32 conn_unacked; | ||
69 | int published; | ||
70 | u32 congested; | ||
71 | u32 ref; | ||
72 | struct tipc_msg phdr; | ||
73 | }; | ||
74 | |||
75 | |||
76 | /** | ||
77 | * tipc_createport_raw - create a native TIPC port and return it's reference | ||
78 | * | ||
79 | * Note: 'dispatcher' and 'wakeup' deliver a locked port. | ||
80 | */ | ||
81 | |||
82 | u32 tipc_createport_raw(void *usr_handle, | ||
83 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), | ||
84 | void (*wakeup)(struct tipc_port *), | ||
85 | const u32 importance); | ||
86 | |||
87 | /* | ||
88 | * tipc_set_msg_option(): port must be locked. | ||
89 | */ | ||
90 | int tipc_set_msg_option(struct tipc_port *tp_ptr, | ||
91 | const char *opt, | ||
92 | const u32 len); | ||
93 | |||
94 | int tipc_reject_msg(struct sk_buff *buf, u32 err); | ||
95 | |||
96 | int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode); | ||
97 | |||
98 | void tipc_acknowledge(u32 port_ref,u32 ack); | ||
99 | |||
100 | struct tipc_port *tipc_get_port(const u32 ref); | ||
101 | |||
102 | void *tipc_get_handle(const u32 ref); | ||
103 | |||
104 | |||
105 | #endif | ||
106 | |||
107 | #endif | ||
108 | |||
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index a7f4c355a91f..22fc886b9695 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h | |||
@@ -88,7 +88,6 @@ enum ib_atomic_cap { | |||
88 | 88 | ||
89 | struct ib_device_attr { | 89 | struct ib_device_attr { |
90 | u64 fw_ver; | 90 | u64 fw_ver; |
91 | __be64 node_guid; | ||
92 | __be64 sys_image_guid; | 91 | __be64 sys_image_guid; |
93 | u64 max_mr_size; | 92 | u64 max_mr_size; |
94 | u64 page_size_cap; | 93 | u64 page_size_cap; |
@@ -951,6 +950,7 @@ struct ib_device { | |||
951 | u64 uverbs_cmd_mask; | 950 | u64 uverbs_cmd_mask; |
952 | int uverbs_abi_ver; | 951 | int uverbs_abi_ver; |
953 | 952 | ||
953 | __be64 node_guid; | ||
954 | u8 node_type; | 954 | u8 node_type; |
955 | u8 phys_port_cnt; | 955 | u8 phys_port_cnt; |
956 | }; | 956 | }; |
diff --git a/net/Kconfig b/net/Kconfig index 60f6f321bd76..9296b269d675 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -159,6 +159,7 @@ source "net/ipx/Kconfig" | |||
159 | source "drivers/net/appletalk/Kconfig" | 159 | source "drivers/net/appletalk/Kconfig" |
160 | source "net/x25/Kconfig" | 160 | source "net/x25/Kconfig" |
161 | source "net/lapb/Kconfig" | 161 | source "net/lapb/Kconfig" |
162 | source "net/tipc/Kconfig" | ||
162 | 163 | ||
163 | config NET_DIVERT | 164 | config NET_DIVERT |
164 | bool "Frame Diverter (EXPERIMENTAL)" | 165 | bool "Frame Diverter (EXPERIMENTAL)" |
diff --git a/net/Makefile b/net/Makefile index f5141b9d4f38..065796f5fb17 100644 --- a/net/Makefile +++ b/net/Makefile | |||
@@ -45,6 +45,7 @@ obj-$(CONFIG_VLAN_8021Q) += 8021q/ | |||
45 | obj-$(CONFIG_IP_DCCP) += dccp/ | 45 | obj-$(CONFIG_IP_DCCP) += dccp/ |
46 | obj-$(CONFIG_IP_SCTP) += sctp/ | 46 | obj-$(CONFIG_IP_SCTP) += sctp/ |
47 | obj-$(CONFIG_IEEE80211) += ieee80211/ | 47 | obj-$(CONFIG_IEEE80211) += ieee80211/ |
48 | obj-$(CONFIG_TIPC) += tipc/ | ||
48 | 49 | ||
49 | ifeq ($(CONFIG_NET),y) | 50 | ifeq ($(CONFIG_NET),y) |
50 | obj-$(CONFIG_SYSCTL) += sysctl_net.o | 51 | obj-$(CONFIG_SYSCTL) += sysctl_net.o |
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 9f6e0193ae10..a29c1232c420 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/netfilter.h> | 15 | #include <linux/netfilter.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/ip.h> | 17 | #include <linux/ip.h> |
18 | #include <linux/in.h> | ||
18 | #include <linux/if_arp.h> | 19 | #include <linux/if_arp.h> |
19 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
20 | 21 | ||
diff --git a/net/core/filter.c b/net/core/filter.c index 9eb9d0017a01..a52665f75224 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -287,7 +287,9 @@ load_b: | |||
287 | * no references or jumps that are out of range, no illegal | 287 | * no references or jumps that are out of range, no illegal |
288 | * instructions, and must end with a RET instruction. | 288 | * instructions, and must end with a RET instruction. |
289 | * | 289 | * |
290 | * Returns 0 if the rule set is legal or a negative errno code if not. | 290 | * All jumps are forward as they are not signed. |
291 | * | ||
292 | * Returns 0 if the rule set is legal or -EINVAL if not. | ||
291 | */ | 293 | */ |
292 | int sk_chk_filter(struct sock_filter *filter, int flen) | 294 | int sk_chk_filter(struct sock_filter *filter, int flen) |
293 | { | 295 | { |
@@ -299,7 +301,6 @@ int sk_chk_filter(struct sock_filter *filter, int flen) | |||
299 | 301 | ||
300 | /* check the filter code now */ | 302 | /* check the filter code now */ |
301 | for (pc = 0; pc < flen; pc++) { | 303 | for (pc = 0; pc < flen; pc++) { |
302 | /* all jumps are forward as they are not signed */ | ||
303 | ftest = &filter[pc]; | 304 | ftest = &filter[pc]; |
304 | 305 | ||
305 | /* Only allow valid instructions */ | 306 | /* Only allow valid instructions */ |
@@ -383,11 +384,6 @@ int sk_chk_filter(struct sock_filter *filter, int flen) | |||
383 | } | 384 | } |
384 | } | 385 | } |
385 | 386 | ||
386 | /* | ||
387 | * The program must end with a return. We don't care where they | ||
388 | * jumped within the script (its always forwards) but in the end | ||
389 | * they _will_ hit this. | ||
390 | */ | ||
391 | return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL; | 387 | return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL; |
392 | } | 388 | } |
393 | 389 | ||
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index a9893ec03e02..db783036e4d8 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -182,6 +182,7 @@ config IP_NF_QUEUE | |||
182 | 182 | ||
183 | config IP_NF_IPTABLES | 183 | config IP_NF_IPTABLES |
184 | tristate "IP tables support (required for filtering/masq/NAT)" | 184 | tristate "IP tables support (required for filtering/masq/NAT)" |
185 | depends on NETFILTER_XTABLES | ||
185 | help | 186 | help |
186 | iptables is a general, extensible packet identification framework. | 187 | iptables is a general, extensible packet identification framework. |
187 | The packet filtering and full NAT (masquerading, port forwarding, | 188 | The packet filtering and full NAT (masquerading, port forwarding, |
@@ -191,16 +192,6 @@ config IP_NF_IPTABLES | |||
191 | To compile it as a module, choose M here. If unsure, say N. | 192 | To compile it as a module, choose M here. If unsure, say N. |
192 | 193 | ||
193 | # The matches. | 194 | # The matches. |
194 | config IP_NF_MATCH_LIMIT | ||
195 | tristate "limit match support" | ||
196 | depends on IP_NF_IPTABLES | ||
197 | help | ||
198 | limit matching allows you to control the rate at which a rule can be | ||
199 | matched: mainly useful in combination with the LOG target ("LOG | ||
200 | target support", below) and to avoid some Denial of Service attacks. | ||
201 | |||
202 | To compile it as a module, choose M here. If unsure, say N. | ||
203 | |||
204 | config IP_NF_MATCH_IPRANGE | 195 | config IP_NF_MATCH_IPRANGE |
205 | tristate "IP range match support" | 196 | tristate "IP range match support" |
206 | depends on IP_NF_IPTABLES | 197 | depends on IP_NF_IPTABLES |
@@ -210,37 +201,6 @@ config IP_NF_MATCH_IPRANGE | |||
210 | 201 | ||
211 | To compile it as a module, choose M here. If unsure, say N. | 202 | To compile it as a module, choose M here. If unsure, say N. |
212 | 203 | ||
213 | config IP_NF_MATCH_MAC | ||
214 | tristate "MAC address match support" | ||
215 | depends on IP_NF_IPTABLES | ||
216 | help | ||
217 | MAC matching allows you to match packets based on the source | ||
218 | Ethernet address of the packet. | ||
219 | |||
220 | To compile it as a module, choose M here. If unsure, say N. | ||
221 | |||
222 | config IP_NF_MATCH_PKTTYPE | ||
223 | tristate "Packet type match support" | ||
224 | depends on IP_NF_IPTABLES | ||
225 | help | ||
226 | Packet type matching allows you to match a packet by | ||
227 | its "class", eg. BROADCAST, MULTICAST, ... | ||
228 | |||
229 | Typical usage: | ||
230 | iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG | ||
231 | |||
232 | To compile it as a module, choose M here. If unsure, say N. | ||
233 | |||
234 | config IP_NF_MATCH_MARK | ||
235 | tristate "netfilter MARK match support" | ||
236 | depends on IP_NF_IPTABLES | ||
237 | help | ||
238 | Netfilter mark matching allows you to match packets based on the | ||
239 | `nfmark' value in the packet. This can be set by the MARK target | ||
240 | (see below). | ||
241 | |||
242 | To compile it as a module, choose M here. If unsure, say N. | ||
243 | |||
244 | config IP_NF_MATCH_MULTIPORT | 204 | config IP_NF_MATCH_MULTIPORT |
245 | tristate "Multiple port match support" | 205 | tristate "Multiple port match support" |
246 | depends on IP_NF_IPTABLES | 206 | depends on IP_NF_IPTABLES |
@@ -301,15 +261,6 @@ config IP_NF_MATCH_AH_ESP | |||
301 | 261 | ||
302 | To compile it as a module, choose M here. If unsure, say N. | 262 | To compile it as a module, choose M here. If unsure, say N. |
303 | 263 | ||
304 | config IP_NF_MATCH_LENGTH | ||
305 | tristate "LENGTH match support" | ||
306 | depends on IP_NF_IPTABLES | ||
307 | help | ||
308 | This option allows you to match the length of a packet against a | ||
309 | specific value or range of values. | ||
310 | |||
311 | To compile it as a module, choose M here. If unsure, say N. | ||
312 | |||
313 | config IP_NF_MATCH_TTL | 264 | config IP_NF_MATCH_TTL |
314 | tristate "TTL match support" | 265 | tristate "TTL match support" |
315 | depends on IP_NF_IPTABLES | 266 | depends on IP_NF_IPTABLES |
@@ -319,50 +270,6 @@ config IP_NF_MATCH_TTL | |||
319 | 270 | ||
320 | To compile it as a module, choose M here. If unsure, say N. | 271 | To compile it as a module, choose M here. If unsure, say N. |
321 | 272 | ||
322 | config IP_NF_MATCH_TCPMSS | ||
323 | tristate "tcpmss match support" | ||
324 | depends on IP_NF_IPTABLES | ||
325 | help | ||
326 | This option adds a `tcpmss' match, which allows you to examine the | ||
327 | MSS value of TCP SYN packets, which control the maximum packet size | ||
328 | for that connection. | ||
329 | |||
330 | To compile it as a module, choose M here. If unsure, say N. | ||
331 | |||
332 | config IP_NF_MATCH_HELPER | ||
333 | tristate "Helper match support" | ||
334 | depends on IP_NF_IPTABLES | ||
335 | depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 | ||
336 | help | ||
337 | Helper matching allows you to match packets in dynamic connections | ||
338 | tracked by a conntrack-helper, ie. ip_conntrack_ftp | ||
339 | |||
340 | To compile it as a module, choose M here. If unsure, say Y. | ||
341 | |||
342 | config IP_NF_MATCH_STATE | ||
343 | tristate "Connection state match support" | ||
344 | depends on IP_NF_IPTABLES | ||
345 | depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 | ||
346 | help | ||
347 | Connection state matching allows you to match packets based on their | ||
348 | relationship to a tracked connection (ie. previous packets). This | ||
349 | is a powerful tool for packet classification. | ||
350 | |||
351 | To compile it as a module, choose M here. If unsure, say N. | ||
352 | |||
353 | config IP_NF_MATCH_CONNTRACK | ||
354 | tristate "Connection tracking match support" | ||
355 | depends on IP_NF_IPTABLES | ||
356 | depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 | ||
357 | help | ||
358 | This is a general conntrack match module, a superset of the state match. | ||
359 | |||
360 | It allows matching on additional conntrack information, which is | ||
361 | useful in complex configurations, such as NAT gateways with multiple | ||
362 | internet links or tunnels. | ||
363 | |||
364 | To compile it as a module, choose M here. If unsure, say N. | ||
365 | |||
366 | config IP_NF_MATCH_OWNER | 273 | config IP_NF_MATCH_OWNER |
367 | tristate "Owner match support" | 274 | tristate "Owner match support" |
368 | depends on IP_NF_IPTABLES | 275 | depends on IP_NF_IPTABLES |
@@ -372,15 +279,6 @@ config IP_NF_MATCH_OWNER | |||
372 | 279 | ||
373 | To compile it as a module, choose M here. If unsure, say N. | 280 | To compile it as a module, choose M here. If unsure, say N. |
374 | 281 | ||
375 | config IP_NF_MATCH_PHYSDEV | ||
376 | tristate "Physdev match support" | ||
377 | depends on IP_NF_IPTABLES && BRIDGE_NETFILTER | ||
378 | help | ||
379 | Physdev packet matching matches against the physical bridge ports | ||
380 | the IP packet arrived on or will leave by. | ||
381 | |||
382 | To compile it as a module, choose M here. If unsure, say N. | ||
383 | |||
384 | config IP_NF_MATCH_ADDRTYPE | 282 | config IP_NF_MATCH_ADDRTYPE |
385 | tristate 'address type match support' | 283 | tristate 'address type match support' |
386 | depends on IP_NF_IPTABLES | 284 | depends on IP_NF_IPTABLES |
@@ -391,75 +289,6 @@ config IP_NF_MATCH_ADDRTYPE | |||
391 | If you want to compile it as a module, say M here and read | 289 | If you want to compile it as a module, say M here and read |
392 | <file:Documentation/modules.txt>. If unsure, say `N'. | 290 | <file:Documentation/modules.txt>. If unsure, say `N'. |
393 | 291 | ||
394 | config IP_NF_MATCH_REALM | ||
395 | tristate 'realm match support' | ||
396 | depends on IP_NF_IPTABLES | ||
397 | select NET_CLS_ROUTE | ||
398 | help | ||
399 | This option adds a `realm' match, which allows you to use the realm | ||
400 | key from the routing subsystem inside iptables. | ||
401 | |||
402 | This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option | ||
403 | in tc world. | ||
404 | |||
405 | If you want to compile it as a module, say M here and read | ||
406 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
407 | |||
408 | config IP_NF_MATCH_SCTP | ||
409 | tristate 'SCTP protocol match support' | ||
410 | depends on IP_NF_IPTABLES | ||
411 | help | ||
412 | With this option enabled, you will be able to use the iptables | ||
413 | `sctp' match in order to match on SCTP source/destination ports | ||
414 | and SCTP chunk types. | ||
415 | |||
416 | If you want to compile it as a module, say M here and read | ||
417 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
418 | |||
419 | config IP_NF_MATCH_DCCP | ||
420 | tristate 'DCCP protocol match support' | ||
421 | depends on IP_NF_IPTABLES | ||
422 | help | ||
423 | With this option enabled, you will be able to use the iptables | ||
424 | `dccp' match in order to match on DCCP source/destination ports | ||
425 | and DCCP flags. | ||
426 | |||
427 | If you want to compile it as a module, say M here and read | ||
428 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
429 | |||
430 | config IP_NF_MATCH_COMMENT | ||
431 | tristate 'comment match support' | ||
432 | depends on IP_NF_IPTABLES | ||
433 | help | ||
434 | This option adds a `comment' dummy-match, which allows you to put | ||
435 | comments in your iptables ruleset. | ||
436 | |||
437 | If you want to compile it as a module, say M here and read | ||
438 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
439 | |||
440 | config IP_NF_MATCH_CONNMARK | ||
441 | tristate 'Connection mark match support' | ||
442 | depends on IP_NF_IPTABLES | ||
443 | depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) | ||
444 | help | ||
445 | This option adds a `connmark' match, which allows you to match the | ||
446 | connection mark value previously set for the session by `CONNMARK'. | ||
447 | |||
448 | If you want to compile it as a module, say M here and read | ||
449 | <file:Documentation/modules.txt>. The module will be called | ||
450 | ipt_connmark.o. If unsure, say `N'. | ||
451 | |||
452 | config IP_NF_MATCH_CONNBYTES | ||
453 | tristate 'Connection byte/packet counter match support' | ||
454 | depends on IP_NF_IPTABLES | ||
455 | depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || (NF_CT_ACCT && NF_CONNTRACK_IPV4) | ||
456 | help | ||
457 | This option adds a `connbytes' match, which allows you to match the | ||
458 | number of bytes and/or packets for each direction within a connection. | ||
459 | |||
460 | If you want to compile it as a module, say M here and read | ||
461 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
462 | |||
463 | config IP_NF_MATCH_HASHLIMIT | 292 | config IP_NF_MATCH_HASHLIMIT |
464 | tristate 'hashlimit match support' | 293 | tristate 'hashlimit match support' |
465 | depends on IP_NF_IPTABLES | 294 | depends on IP_NF_IPTABLES |
@@ -474,19 +303,6 @@ config IP_NF_MATCH_HASHLIMIT | |||
474 | destination IP' or `500pps from any given source IP' with a single | 303 | destination IP' or `500pps from any given source IP' with a single |
475 | IPtables rule. | 304 | IPtables rule. |
476 | 305 | ||
477 | config IP_NF_MATCH_STRING | ||
478 | tristate 'string match support' | ||
479 | depends on IP_NF_IPTABLES | ||
480 | select TEXTSEARCH | ||
481 | select TEXTSEARCH_KMP | ||
482 | select TEXTSEARCH_BM | ||
483 | select TEXTSEARCH_FSM | ||
484 | help | ||
485 | This option adds a `string' match, which allows you to look for | ||
486 | pattern matchings in packets. | ||
487 | |||
488 | To compile it as a module, choose M here. If unsure, say N. | ||
489 | |||
490 | config IP_NF_MATCH_POLICY | 306 | config IP_NF_MATCH_POLICY |
491 | tristate "IPsec policy match support" | 307 | tristate "IPsec policy match support" |
492 | depends on IP_NF_IPTABLES && XFRM | 308 | depends on IP_NF_IPTABLES && XFRM |
@@ -572,17 +388,6 @@ config IP_NF_TARGET_TCPMSS | |||
572 | 388 | ||
573 | To compile it as a module, choose M here. If unsure, say N. | 389 | To compile it as a module, choose M here. If unsure, say N. |
574 | 390 | ||
575 | config IP_NF_TARGET_NFQUEUE | ||
576 | tristate "NFQUEUE Target Support" | ||
577 | depends on IP_NF_IPTABLES | ||
578 | help | ||
579 | This Target replaced the old obsolete QUEUE target. | ||
580 | |||
581 | As opposed to QUEUE, it supports 65535 different queues, | ||
582 | not just one. | ||
583 | |||
584 | To compile it as a module, choose M here. If unsure, say N. | ||
585 | |||
586 | # NAT + specific targets | 391 | # NAT + specific targets |
587 | config IP_NF_NAT | 392 | config IP_NF_NAT |
588 | tristate "Full NAT" | 393 | tristate "Full NAT" |
@@ -735,31 +540,6 @@ config IP_NF_TARGET_DSCP | |||
735 | 540 | ||
736 | To compile it as a module, choose M here. If unsure, say N. | 541 | To compile it as a module, choose M here. If unsure, say N. |
737 | 542 | ||
738 | config IP_NF_TARGET_MARK | ||
739 | tristate "MARK target support" | ||
740 | depends on IP_NF_MANGLE | ||
741 | help | ||
742 | This option adds a `MARK' target, which allows you to create rules | ||
743 | in the `mangle' table which alter the netfilter mark (nfmark) field | ||
744 | associated with the packet prior to routing. This can change | ||
745 | the routing method (see `Use netfilter MARK value as routing | ||
746 | key') and can also be used by other subsystems to change their | ||
747 | behavior. | ||
748 | |||
749 | To compile it as a module, choose M here. If unsure, say N. | ||
750 | |||
751 | config IP_NF_TARGET_CLASSIFY | ||
752 | tristate "CLASSIFY target support" | ||
753 | depends on IP_NF_MANGLE | ||
754 | help | ||
755 | This option adds a `CLASSIFY' target, which enables the user to set | ||
756 | the priority of a packet. Some qdiscs can use this value for | ||
757 | classification, among these are: | ||
758 | |||
759 | atm, cbq, dsmark, pfifo_fast, htb, prio | ||
760 | |||
761 | To compile it as a module, choose M here. If unsure, say N. | ||
762 | |||
763 | config IP_NF_TARGET_TTL | 543 | config IP_NF_TARGET_TTL |
764 | tristate 'TTL target support' | 544 | tristate 'TTL target support' |
765 | depends on IP_NF_MANGLE | 545 | depends on IP_NF_MANGLE |
@@ -774,19 +554,6 @@ config IP_NF_TARGET_TTL | |||
774 | 554 | ||
775 | To compile it as a module, choose M here. If unsure, say N. | 555 | To compile it as a module, choose M here. If unsure, say N. |
776 | 556 | ||
777 | config IP_NF_TARGET_CONNMARK | ||
778 | tristate 'CONNMARK target support' | ||
779 | depends on IP_NF_MANGLE | ||
780 | depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) | ||
781 | help | ||
782 | This option adds a `CONNMARK' target, which allows one to manipulate | ||
783 | the connection mark value. Similar to the MARK target, but | ||
784 | affects the connection mark value rather than the packet mark value. | ||
785 | |||
786 | If you want to compile it as a module, say M here and read | ||
787 | <file:Documentation/modules.txt>. The module will be called | ||
788 | ipt_CONNMARK.o. If unsure, say `N'. | ||
789 | |||
790 | config IP_NF_TARGET_CLUSTERIP | 557 | config IP_NF_TARGET_CLUSTERIP |
791 | tristate "CLUSTERIP target support (EXPERIMENTAL)" | 558 | tristate "CLUSTERIP target support (EXPERIMENTAL)" |
792 | depends on IP_NF_MANGLE && EXPERIMENTAL | 559 | depends on IP_NF_MANGLE && EXPERIMENTAL |
@@ -810,23 +577,10 @@ config IP_NF_RAW | |||
810 | If you want to compile it as a module, say M here and read | 577 | If you want to compile it as a module, say M here and read |
811 | <file:Documentation/modules.txt>. If unsure, say `N'. | 578 | <file:Documentation/modules.txt>. If unsure, say `N'. |
812 | 579 | ||
813 | config IP_NF_TARGET_NOTRACK | ||
814 | tristate 'NOTRACK target support' | ||
815 | depends on IP_NF_RAW | ||
816 | depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 | ||
817 | help | ||
818 | The NOTRACK target allows a select rule to specify | ||
819 | which packets *not* to enter the conntrack/NAT | ||
820 | subsystem with all the consequences (no ICMP error tracking, | ||
821 | no protocol helpers for the selected packets). | ||
822 | |||
823 | If you want to compile it as a module, say M here and read | ||
824 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
825 | |||
826 | |||
827 | # ARP tables | 580 | # ARP tables |
828 | config IP_NF_ARPTABLES | 581 | config IP_NF_ARPTABLES |
829 | tristate "ARP tables support" | 582 | tristate "ARP tables support" |
583 | depends on NETFILTER_XTABLES | ||
830 | help | 584 | help |
831 | arptables is a general, extensible packet identification framework. | 585 | arptables is a general, extensible packet identification framework. |
832 | The ARP packet filtering and mangling (manipulation)subsystems | 586 | The ARP packet filtering and mangling (manipulation)subsystems |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 549b01a648b3..bcefe64b9317 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -47,14 +47,8 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o | |||
47 | 47 | ||
48 | # matches | 48 | # matches |
49 | obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o | 49 | obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o |
50 | obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o | ||
51 | obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o | 50 | obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o |
52 | obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o | ||
53 | obj-$(CONFIG_IP_NF_MATCH_DCCP) += ipt_dccp.o | ||
54 | obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o | ||
55 | obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o | ||
56 | obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o | 51 | obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o |
57 | obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o | ||
58 | obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o | 52 | obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o |
59 | obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o | 53 | obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o |
60 | obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o | 54 | obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o |
@@ -62,40 +56,25 @@ obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o | |||
62 | obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o | 56 | obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o |
63 | obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o | 57 | obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o |
64 | obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o | 58 | obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o |
65 | obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o | ||
66 | obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o | 59 | obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o |
67 | obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o | ||
68 | obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o | ||
69 | obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o | ||
70 | obj-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes.o | ||
71 | obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o | ||
72 | obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o | ||
73 | obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o | 60 | obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o |
74 | obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o | ||
75 | obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o | 61 | obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o |
76 | obj-$(CONFIG_IP_NF_MATCH_COMMENT) += ipt_comment.o | ||
77 | obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o | ||
78 | 62 | ||
79 | # targets | 63 | # targets |
80 | obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o | 64 | obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o |
81 | obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o | 65 | obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o |
82 | obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o | 66 | obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o |
83 | obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o | 67 | obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o |
84 | obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o | ||
85 | obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o | 68 | obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o |
86 | obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o | 69 | obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o |
87 | obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o | 70 | obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o |
88 | obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o | 71 | obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o |
89 | obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o | ||
90 | obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o | 72 | obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o |
91 | obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o | 73 | obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o |
92 | obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o | ||
93 | obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o | 74 | obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o |
94 | obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o | 75 | obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o |
95 | obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o | ||
96 | obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o | 76 | obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o |
97 | obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o | 77 | obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o |
98 | obj-$(CONFIG_IP_NF_TARGET_NFQUEUE) += ipt_NFQUEUE.o | ||
99 | 78 | ||
100 | # generic ARP tables | 79 | # generic ARP tables |
101 | obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o | 80 | obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index b6d5284c8020..afe3d8f8177d 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
25 | #include <asm/semaphore.h> | 25 | #include <asm/semaphore.h> |
26 | 26 | ||
27 | #include <linux/netfilter/x_tables.h> | ||
27 | #include <linux/netfilter_arp/arp_tables.h> | 28 | #include <linux/netfilter_arp/arp_tables.h> |
28 | 29 | ||
29 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
@@ -55,28 +56,9 @@ do { \ | |||
55 | #else | 56 | #else |
56 | #define ARP_NF_ASSERT(x) | 57 | #define ARP_NF_ASSERT(x) |
57 | #endif | 58 | #endif |
58 | #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) | ||
59 | 59 | ||
60 | static DECLARE_MUTEX(arpt_mutex); | ||
61 | |||
62 | #define ASSERT_READ_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0) | ||
63 | #define ASSERT_WRITE_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0) | ||
64 | #include <linux/netfilter_ipv4/listhelp.h> | 60 | #include <linux/netfilter_ipv4/listhelp.h> |
65 | 61 | ||
66 | struct arpt_table_info { | ||
67 | unsigned int size; | ||
68 | unsigned int number; | ||
69 | unsigned int initial_entries; | ||
70 | unsigned int hook_entry[NF_ARP_NUMHOOKS]; | ||
71 | unsigned int underflow[NF_ARP_NUMHOOKS]; | ||
72 | void *entries[NR_CPUS]; | ||
73 | }; | ||
74 | |||
75 | static LIST_HEAD(arpt_target); | ||
76 | static LIST_HEAD(arpt_tables); | ||
77 | #define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) | ||
78 | #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) | ||
79 | |||
80 | static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, | 62 | static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, |
81 | char *hdr_addr, int len) | 63 | char *hdr_addr, int len) |
82 | { | 64 | { |
@@ -223,9 +205,9 @@ static inline int arp_checkentry(const struct arpt_arp *arp) | |||
223 | } | 205 | } |
224 | 206 | ||
225 | static unsigned int arpt_error(struct sk_buff **pskb, | 207 | static unsigned int arpt_error(struct sk_buff **pskb, |
226 | unsigned int hooknum, | ||
227 | const struct net_device *in, | 208 | const struct net_device *in, |
228 | const struct net_device *out, | 209 | const struct net_device *out, |
210 | unsigned int hooknum, | ||
229 | const void *targinfo, | 211 | const void *targinfo, |
230 | void *userinfo) | 212 | void *userinfo) |
231 | { | 213 | { |
@@ -254,6 +236,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
254 | struct arpt_entry *e, *back; | 236 | struct arpt_entry *e, *back; |
255 | const char *indev, *outdev; | 237 | const char *indev, *outdev; |
256 | void *table_base; | 238 | void *table_base; |
239 | struct xt_table_info *private = table->private; | ||
257 | 240 | ||
258 | /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ | 241 | /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ |
259 | if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) + | 242 | if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) + |
@@ -265,9 +248,9 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
265 | outdev = out ? out->name : nulldevname; | 248 | outdev = out ? out->name : nulldevname; |
266 | 249 | ||
267 | read_lock_bh(&table->lock); | 250 | read_lock_bh(&table->lock); |
268 | table_base = (void *)table->private->entries[smp_processor_id()]; | 251 | table_base = (void *)private->entries[smp_processor_id()]; |
269 | e = get_entry(table_base, table->private->hook_entry[hook]); | 252 | e = get_entry(table_base, private->hook_entry[hook]); |
270 | back = get_entry(table_base, table->private->underflow[hook]); | 253 | back = get_entry(table_base, private->underflow[hook]); |
271 | 254 | ||
272 | arp = (*pskb)->nh.arph; | 255 | arp = (*pskb)->nh.arph; |
273 | do { | 256 | do { |
@@ -315,8 +298,8 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
315 | * abs. verdicts | 298 | * abs. verdicts |
316 | */ | 299 | */ |
317 | verdict = t->u.kernel.target->target(pskb, | 300 | verdict = t->u.kernel.target->target(pskb, |
318 | hook, | ||
319 | in, out, | 301 | in, out, |
302 | hook, | ||
320 | t->data, | 303 | t->data, |
321 | userdata); | 304 | userdata); |
322 | 305 | ||
@@ -341,106 +324,6 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
341 | return verdict; | 324 | return verdict; |
342 | } | 325 | } |
343 | 326 | ||
344 | /* | ||
345 | * These are weird, but module loading must not be done with mutex | ||
346 | * held (since they will register), and we have to have a single | ||
347 | * function to use try_then_request_module(). | ||
348 | */ | ||
349 | |||
350 | /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ | ||
351 | static inline struct arpt_table *find_table_lock(const char *name) | ||
352 | { | ||
353 | struct arpt_table *t; | ||
354 | |||
355 | if (down_interruptible(&arpt_mutex) != 0) | ||
356 | return ERR_PTR(-EINTR); | ||
357 | |||
358 | list_for_each_entry(t, &arpt_tables, list) | ||
359 | if (strcmp(t->name, name) == 0 && try_module_get(t->me)) | ||
360 | return t; | ||
361 | up(&arpt_mutex); | ||
362 | return NULL; | ||
363 | } | ||
364 | |||
365 | |||
366 | /* Find target, grabs ref. Returns ERR_PTR() on error. */ | ||
367 | static inline struct arpt_target *find_target(const char *name, u8 revision) | ||
368 | { | ||
369 | struct arpt_target *t; | ||
370 | int err = 0; | ||
371 | |||
372 | if (down_interruptible(&arpt_mutex) != 0) | ||
373 | return ERR_PTR(-EINTR); | ||
374 | |||
375 | list_for_each_entry(t, &arpt_target, list) { | ||
376 | if (strcmp(t->name, name) == 0) { | ||
377 | if (t->revision == revision) { | ||
378 | if (try_module_get(t->me)) { | ||
379 | up(&arpt_mutex); | ||
380 | return t; | ||
381 | } | ||
382 | } else | ||
383 | err = -EPROTOTYPE; /* Found something. */ | ||
384 | } | ||
385 | } | ||
386 | up(&arpt_mutex); | ||
387 | return ERR_PTR(err); | ||
388 | } | ||
389 | |||
390 | struct arpt_target *arpt_find_target(const char *name, u8 revision) | ||
391 | { | ||
392 | struct arpt_target *target; | ||
393 | |||
394 | target = try_then_request_module(find_target(name, revision), | ||
395 | "arpt_%s", name); | ||
396 | if (IS_ERR(target) || !target) | ||
397 | return NULL; | ||
398 | return target; | ||
399 | } | ||
400 | |||
401 | static int target_revfn(const char *name, u8 revision, int *bestp) | ||
402 | { | ||
403 | struct arpt_target *t; | ||
404 | int have_rev = 0; | ||
405 | |||
406 | list_for_each_entry(t, &arpt_target, list) { | ||
407 | if (strcmp(t->name, name) == 0) { | ||
408 | if (t->revision > *bestp) | ||
409 | *bestp = t->revision; | ||
410 | if (t->revision == revision) | ||
411 | have_rev =1; | ||
412 | } | ||
413 | } | ||
414 | return have_rev; | ||
415 | } | ||
416 | |||
417 | /* Returns true or false (if no such extension at all) */ | ||
418 | static inline int find_revision(const char *name, u8 revision, | ||
419 | int (*revfn)(const char *, u8, int *), | ||
420 | int *err) | ||
421 | { | ||
422 | int have_rev, best = -1; | ||
423 | |||
424 | if (down_interruptible(&arpt_mutex) != 0) { | ||
425 | *err = -EINTR; | ||
426 | return 1; | ||
427 | } | ||
428 | have_rev = revfn(name, revision, &best); | ||
429 | up(&arpt_mutex); | ||
430 | |||
431 | /* Nothing at all? Return 0 to try loading module. */ | ||
432 | if (best == -1) { | ||
433 | *err = -ENOENT; | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | *err = best; | ||
438 | if (!have_rev) | ||
439 | *err = -EPROTONOSUPPORT; | ||
440 | return 1; | ||
441 | } | ||
442 | |||
443 | |||
444 | /* All zeroes == unconditional rule. */ | 327 | /* All zeroes == unconditional rule. */ |
445 | static inline int unconditional(const struct arpt_arp *arp) | 328 | static inline int unconditional(const struct arpt_arp *arp) |
446 | { | 329 | { |
@@ -456,7 +339,7 @@ static inline int unconditional(const struct arpt_arp *arp) | |||
456 | /* Figures out from what hook each rule can be called: returns 0 if | 339 | /* Figures out from what hook each rule can be called: returns 0 if |
457 | * there are loops. Puts hook bitmask in comefrom. | 340 | * there are loops. Puts hook bitmask in comefrom. |
458 | */ | 341 | */ |
459 | static int mark_source_chains(struct arpt_table_info *newinfo, | 342 | static int mark_source_chains(struct xt_table_info *newinfo, |
460 | unsigned int valid_hooks, void *entry0) | 343 | unsigned int valid_hooks, void *entry0) |
461 | { | 344 | { |
462 | unsigned int hook; | 345 | unsigned int hook; |
@@ -587,8 +470,8 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i | |||
587 | } | 470 | } |
588 | 471 | ||
589 | t = arpt_get_target(e); | 472 | t = arpt_get_target(e); |
590 | target = try_then_request_module(find_target(t->u.user.name, | 473 | target = try_then_request_module(xt_find_target(NF_ARP, t->u.user.name, |
591 | t->u.user.revision), | 474 | t->u.user.revision), |
592 | "arpt_%s", t->u.user.name); | 475 | "arpt_%s", t->u.user.name); |
593 | if (IS_ERR(target) || !target) { | 476 | if (IS_ERR(target) || !target) { |
594 | duprintf("check_entry: `%s' not found\n", t->u.user.name); | 477 | duprintf("check_entry: `%s' not found\n", t->u.user.name); |
@@ -622,7 +505,7 @@ out: | |||
622 | } | 505 | } |
623 | 506 | ||
624 | static inline int check_entry_size_and_hooks(struct arpt_entry *e, | 507 | static inline int check_entry_size_and_hooks(struct arpt_entry *e, |
625 | struct arpt_table_info *newinfo, | 508 | struct xt_table_info *newinfo, |
626 | unsigned char *base, | 509 | unsigned char *base, |
627 | unsigned char *limit, | 510 | unsigned char *limit, |
628 | const unsigned int *hook_entries, | 511 | const unsigned int *hook_entries, |
@@ -656,7 +539,7 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, | |||
656 | < 0 (not ARPT_RETURN). --RR */ | 539 | < 0 (not ARPT_RETURN). --RR */ |
657 | 540 | ||
658 | /* Clear counters and comefrom */ | 541 | /* Clear counters and comefrom */ |
659 | e->counters = ((struct arpt_counters) { 0, 0 }); | 542 | e->counters = ((struct xt_counters) { 0, 0 }); |
660 | e->comefrom = 0; | 543 | e->comefrom = 0; |
661 | 544 | ||
662 | (*i)++; | 545 | (*i)++; |
@@ -683,7 +566,7 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i) | |||
683 | */ | 566 | */ |
684 | static int translate_table(const char *name, | 567 | static int translate_table(const char *name, |
685 | unsigned int valid_hooks, | 568 | unsigned int valid_hooks, |
686 | struct arpt_table_info *newinfo, | 569 | struct xt_table_info *newinfo, |
687 | void *entry0, | 570 | void *entry0, |
688 | unsigned int size, | 571 | unsigned int size, |
689 | unsigned int number, | 572 | unsigned int number, |
@@ -764,34 +647,9 @@ static int translate_table(const char *name, | |||
764 | return ret; | 647 | return ret; |
765 | } | 648 | } |
766 | 649 | ||
767 | static struct arpt_table_info *replace_table(struct arpt_table *table, | ||
768 | unsigned int num_counters, | ||
769 | struct arpt_table_info *newinfo, | ||
770 | int *error) | ||
771 | { | ||
772 | struct arpt_table_info *oldinfo; | ||
773 | |||
774 | /* Do the substitution. */ | ||
775 | write_lock_bh(&table->lock); | ||
776 | /* Check inside lock: is the old number correct? */ | ||
777 | if (num_counters != table->private->number) { | ||
778 | duprintf("num_counters != table->private->number (%u/%u)\n", | ||
779 | num_counters, table->private->number); | ||
780 | write_unlock_bh(&table->lock); | ||
781 | *error = -EAGAIN; | ||
782 | return NULL; | ||
783 | } | ||
784 | oldinfo = table->private; | ||
785 | table->private = newinfo; | ||
786 | newinfo->initial_entries = oldinfo->initial_entries; | ||
787 | write_unlock_bh(&table->lock); | ||
788 | |||
789 | return oldinfo; | ||
790 | } | ||
791 | |||
792 | /* Gets counters. */ | 650 | /* Gets counters. */ |
793 | static inline int add_entry_to_counter(const struct arpt_entry *e, | 651 | static inline int add_entry_to_counter(const struct arpt_entry *e, |
794 | struct arpt_counters total[], | 652 | struct xt_counters total[], |
795 | unsigned int *i) | 653 | unsigned int *i) |
796 | { | 654 | { |
797 | ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); | 655 | ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); |
@@ -801,7 +659,7 @@ static inline int add_entry_to_counter(const struct arpt_entry *e, | |||
801 | } | 659 | } |
802 | 660 | ||
803 | static inline int set_entry_to_counter(const struct arpt_entry *e, | 661 | static inline int set_entry_to_counter(const struct arpt_entry *e, |
804 | struct arpt_counters total[], | 662 | struct xt_counters total[], |
805 | unsigned int *i) | 663 | unsigned int *i) |
806 | { | 664 | { |
807 | SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); | 665 | SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); |
@@ -810,8 +668,8 @@ static inline int set_entry_to_counter(const struct arpt_entry *e, | |||
810 | return 0; | 668 | return 0; |
811 | } | 669 | } |
812 | 670 | ||
813 | static void get_counters(const struct arpt_table_info *t, | 671 | static void get_counters(const struct xt_table_info *t, |
814 | struct arpt_counters counters[]) | 672 | struct xt_counters counters[]) |
815 | { | 673 | { |
816 | unsigned int cpu; | 674 | unsigned int cpu; |
817 | unsigned int i; | 675 | unsigned int i; |
@@ -849,7 +707,8 @@ static int copy_entries_to_user(unsigned int total_size, | |||
849 | { | 707 | { |
850 | unsigned int off, num, countersize; | 708 | unsigned int off, num, countersize; |
851 | struct arpt_entry *e; | 709 | struct arpt_entry *e; |
852 | struct arpt_counters *counters; | 710 | struct xt_counters *counters; |
711 | struct xt_table_info *private = table->private; | ||
853 | int ret = 0; | 712 | int ret = 0; |
854 | void *loc_cpu_entry; | 713 | void *loc_cpu_entry; |
855 | 714 | ||
@@ -857,18 +716,18 @@ static int copy_entries_to_user(unsigned int total_size, | |||
857 | * (other than comefrom, which userspace doesn't care | 716 | * (other than comefrom, which userspace doesn't care |
858 | * about). | 717 | * about). |
859 | */ | 718 | */ |
860 | countersize = sizeof(struct arpt_counters) * table->private->number; | 719 | countersize = sizeof(struct xt_counters) * private->number; |
861 | counters = vmalloc(countersize); | 720 | counters = vmalloc_node(countersize, numa_node_id()); |
862 | 721 | ||
863 | if (counters == NULL) | 722 | if (counters == NULL) |
864 | return -ENOMEM; | 723 | return -ENOMEM; |
865 | 724 | ||
866 | /* First, sum counters... */ | 725 | /* First, sum counters... */ |
867 | write_lock_bh(&table->lock); | 726 | write_lock_bh(&table->lock); |
868 | get_counters(table->private, counters); | 727 | get_counters(private, counters); |
869 | write_unlock_bh(&table->lock); | 728 | write_unlock_bh(&table->lock); |
870 | 729 | ||
871 | loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; | 730 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
872 | /* ... then copy entire thing ... */ | 731 | /* ... then copy entire thing ... */ |
873 | if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { | 732 | if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { |
874 | ret = -EFAULT; | 733 | ret = -EFAULT; |
@@ -911,75 +770,34 @@ static int get_entries(const struct arpt_get_entries *entries, | |||
911 | int ret; | 770 | int ret; |
912 | struct arpt_table *t; | 771 | struct arpt_table *t; |
913 | 772 | ||
914 | t = find_table_lock(entries->name); | 773 | t = xt_find_table_lock(NF_ARP, entries->name); |
915 | if (t || !IS_ERR(t)) { | 774 | if (t || !IS_ERR(t)) { |
775 | struct xt_table_info *private = t->private; | ||
916 | duprintf("t->private->number = %u\n", | 776 | duprintf("t->private->number = %u\n", |
917 | t->private->number); | 777 | private->number); |
918 | if (entries->size == t->private->size) | 778 | if (entries->size == private->size) |
919 | ret = copy_entries_to_user(t->private->size, | 779 | ret = copy_entries_to_user(private->size, |
920 | t, uptr->entrytable); | 780 | t, uptr->entrytable); |
921 | else { | 781 | else { |
922 | duprintf("get_entries: I've got %u not %u!\n", | 782 | duprintf("get_entries: I've got %u not %u!\n", |
923 | t->private->size, | 783 | private->size, entries->size); |
924 | entries->size); | ||
925 | ret = -EINVAL; | 784 | ret = -EINVAL; |
926 | } | 785 | } |
927 | module_put(t->me); | 786 | module_put(t->me); |
928 | up(&arpt_mutex); | 787 | xt_table_unlock(t); |
929 | } else | 788 | } else |
930 | ret = t ? PTR_ERR(t) : -ENOENT; | 789 | ret = t ? PTR_ERR(t) : -ENOENT; |
931 | 790 | ||
932 | return ret; | 791 | return ret; |
933 | } | 792 | } |
934 | 793 | ||
935 | static void free_table_info(struct arpt_table_info *info) | ||
936 | { | ||
937 | int cpu; | ||
938 | for_each_cpu(cpu) { | ||
939 | if (info->size <= PAGE_SIZE) | ||
940 | kfree(info->entries[cpu]); | ||
941 | else | ||
942 | vfree(info->entries[cpu]); | ||
943 | } | ||
944 | kfree(info); | ||
945 | } | ||
946 | |||
947 | static struct arpt_table_info *alloc_table_info(unsigned int size) | ||
948 | { | ||
949 | struct arpt_table_info *newinfo; | ||
950 | int cpu; | ||
951 | |||
952 | newinfo = kzalloc(sizeof(struct arpt_table_info), GFP_KERNEL); | ||
953 | if (!newinfo) | ||
954 | return NULL; | ||
955 | |||
956 | newinfo->size = size; | ||
957 | |||
958 | for_each_cpu(cpu) { | ||
959 | if (size <= PAGE_SIZE) | ||
960 | newinfo->entries[cpu] = kmalloc_node(size, | ||
961 | GFP_KERNEL, | ||
962 | cpu_to_node(cpu)); | ||
963 | else | ||
964 | newinfo->entries[cpu] = vmalloc_node(size, | ||
965 | cpu_to_node(cpu)); | ||
966 | |||
967 | if (newinfo->entries[cpu] == NULL) { | ||
968 | free_table_info(newinfo); | ||
969 | return NULL; | ||
970 | } | ||
971 | } | ||
972 | |||
973 | return newinfo; | ||
974 | } | ||
975 | |||
976 | static int do_replace(void __user *user, unsigned int len) | 794 | static int do_replace(void __user *user, unsigned int len) |
977 | { | 795 | { |
978 | int ret; | 796 | int ret; |
979 | struct arpt_replace tmp; | 797 | struct arpt_replace tmp; |
980 | struct arpt_table *t; | 798 | struct arpt_table *t; |
981 | struct arpt_table_info *newinfo, *oldinfo; | 799 | struct xt_table_info *newinfo, *oldinfo; |
982 | struct arpt_counters *counters; | 800 | struct xt_counters *counters; |
983 | void *loc_cpu_entry, *loc_cpu_old_entry; | 801 | void *loc_cpu_entry, *loc_cpu_old_entry; |
984 | 802 | ||
985 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) | 803 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) |
@@ -989,11 +807,7 @@ static int do_replace(void __user *user, unsigned int len) | |||
989 | if (len != sizeof(tmp) + tmp.size) | 807 | if (len != sizeof(tmp) + tmp.size) |
990 | return -ENOPROTOOPT; | 808 | return -ENOPROTOOPT; |
991 | 809 | ||
992 | /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ | 810 | newinfo = xt_alloc_table_info(tmp.size); |
993 | if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages) | ||
994 | return -ENOMEM; | ||
995 | |||
996 | newinfo = alloc_table_info(tmp.size); | ||
997 | if (!newinfo) | 811 | if (!newinfo) |
998 | return -ENOMEM; | 812 | return -ENOMEM; |
999 | 813 | ||
@@ -1005,7 +819,7 @@ static int do_replace(void __user *user, unsigned int len) | |||
1005 | goto free_newinfo; | 819 | goto free_newinfo; |
1006 | } | 820 | } |
1007 | 821 | ||
1008 | counters = vmalloc(tmp.num_counters * sizeof(struct arpt_counters)); | 822 | counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters)); |
1009 | if (!counters) { | 823 | if (!counters) { |
1010 | ret = -ENOMEM; | 824 | ret = -ENOMEM; |
1011 | goto free_newinfo; | 825 | goto free_newinfo; |
@@ -1019,7 +833,7 @@ static int do_replace(void __user *user, unsigned int len) | |||
1019 | 833 | ||
1020 | duprintf("arp_tables: Translated table\n"); | 834 | duprintf("arp_tables: Translated table\n"); |
1021 | 835 | ||
1022 | t = try_then_request_module(find_table_lock(tmp.name), | 836 | t = try_then_request_module(xt_find_table_lock(NF_ARP, tmp.name), |
1023 | "arptable_%s", tmp.name); | 837 | "arptable_%s", tmp.name); |
1024 | if (!t || IS_ERR(t)) { | 838 | if (!t || IS_ERR(t)) { |
1025 | ret = t ? PTR_ERR(t) : -ENOENT; | 839 | ret = t ? PTR_ERR(t) : -ENOENT; |
@@ -1034,7 +848,7 @@ static int do_replace(void __user *user, unsigned int len) | |||
1034 | goto put_module; | 848 | goto put_module; |
1035 | } | 849 | } |
1036 | 850 | ||
1037 | oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); | 851 | oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret); |
1038 | if (!oldinfo) | 852 | if (!oldinfo) |
1039 | goto put_module; | 853 | goto put_module; |
1040 | 854 | ||
@@ -1054,23 +868,23 @@ static int do_replace(void __user *user, unsigned int len) | |||
1054 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; | 868 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; |
1055 | ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); | 869 | ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); |
1056 | 870 | ||
1057 | free_table_info(oldinfo); | 871 | xt_free_table_info(oldinfo); |
1058 | if (copy_to_user(tmp.counters, counters, | 872 | if (copy_to_user(tmp.counters, counters, |
1059 | sizeof(struct arpt_counters) * tmp.num_counters) != 0) | 873 | sizeof(struct xt_counters) * tmp.num_counters) != 0) |
1060 | ret = -EFAULT; | 874 | ret = -EFAULT; |
1061 | vfree(counters); | 875 | vfree(counters); |
1062 | up(&arpt_mutex); | 876 | xt_table_unlock(t); |
1063 | return ret; | 877 | return ret; |
1064 | 878 | ||
1065 | put_module: | 879 | put_module: |
1066 | module_put(t->me); | 880 | module_put(t->me); |
1067 | up(&arpt_mutex); | 881 | xt_table_unlock(t); |
1068 | free_newinfo_counters_untrans: | 882 | free_newinfo_counters_untrans: |
1069 | ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); | 883 | ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); |
1070 | free_newinfo_counters: | 884 | free_newinfo_counters: |
1071 | vfree(counters); | 885 | vfree(counters); |
1072 | free_newinfo: | 886 | free_newinfo: |
1073 | free_table_info(newinfo); | 887 | xt_free_table_info(newinfo); |
1074 | return ret; | 888 | return ret; |
1075 | } | 889 | } |
1076 | 890 | ||
@@ -1078,7 +892,7 @@ static int do_replace(void __user *user, unsigned int len) | |||
1078 | * and everything is OK. | 892 | * and everything is OK. |
1079 | */ | 893 | */ |
1080 | static inline int add_counter_to_entry(struct arpt_entry *e, | 894 | static inline int add_counter_to_entry(struct arpt_entry *e, |
1081 | const struct arpt_counters addme[], | 895 | const struct xt_counters addme[], |
1082 | unsigned int *i) | 896 | unsigned int *i) |
1083 | { | 897 | { |
1084 | 898 | ||
@@ -1091,15 +905,16 @@ static inline int add_counter_to_entry(struct arpt_entry *e, | |||
1091 | static int do_add_counters(void __user *user, unsigned int len) | 905 | static int do_add_counters(void __user *user, unsigned int len) |
1092 | { | 906 | { |
1093 | unsigned int i; | 907 | unsigned int i; |
1094 | struct arpt_counters_info tmp, *paddc; | 908 | struct xt_counters_info tmp, *paddc; |
1095 | struct arpt_table *t; | 909 | struct arpt_table *t; |
910 | struct xt_table_info *private; | ||
1096 | int ret = 0; | 911 | int ret = 0; |
1097 | void *loc_cpu_entry; | 912 | void *loc_cpu_entry; |
1098 | 913 | ||
1099 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) | 914 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) |
1100 | return -EFAULT; | 915 | return -EFAULT; |
1101 | 916 | ||
1102 | if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct arpt_counters)) | 917 | if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters)) |
1103 | return -EINVAL; | 918 | return -EINVAL; |
1104 | 919 | ||
1105 | paddc = vmalloc(len); | 920 | paddc = vmalloc(len); |
@@ -1111,29 +926,30 @@ static int do_add_counters(void __user *user, unsigned int len) | |||
1111 | goto free; | 926 | goto free; |
1112 | } | 927 | } |
1113 | 928 | ||
1114 | t = find_table_lock(tmp.name); | 929 | t = xt_find_table_lock(NF_ARP, tmp.name); |
1115 | if (!t || IS_ERR(t)) { | 930 | if (!t || IS_ERR(t)) { |
1116 | ret = t ? PTR_ERR(t) : -ENOENT; | 931 | ret = t ? PTR_ERR(t) : -ENOENT; |
1117 | goto free; | 932 | goto free; |
1118 | } | 933 | } |
1119 | 934 | ||
1120 | write_lock_bh(&t->lock); | 935 | write_lock_bh(&t->lock); |
1121 | if (t->private->number != paddc->num_counters) { | 936 | private = t->private; |
937 | if (private->number != paddc->num_counters) { | ||
1122 | ret = -EINVAL; | 938 | ret = -EINVAL; |
1123 | goto unlock_up_free; | 939 | goto unlock_up_free; |
1124 | } | 940 | } |
1125 | 941 | ||
1126 | i = 0; | 942 | i = 0; |
1127 | /* Choose the copy that is on our node */ | 943 | /* Choose the copy that is on our node */ |
1128 | loc_cpu_entry = t->private->entries[smp_processor_id()]; | 944 | loc_cpu_entry = private->entries[smp_processor_id()]; |
1129 | ARPT_ENTRY_ITERATE(loc_cpu_entry, | 945 | ARPT_ENTRY_ITERATE(loc_cpu_entry, |
1130 | t->private->size, | 946 | private->size, |
1131 | add_counter_to_entry, | 947 | add_counter_to_entry, |
1132 | paddc->counters, | 948 | paddc->counters, |
1133 | &i); | 949 | &i); |
1134 | unlock_up_free: | 950 | unlock_up_free: |
1135 | write_unlock_bh(&t->lock); | 951 | write_unlock_bh(&t->lock); |
1136 | up(&arpt_mutex); | 952 | xt_table_unlock(t); |
1137 | module_put(t->me); | 953 | module_put(t->me); |
1138 | free: | 954 | free: |
1139 | vfree(paddc); | 955 | vfree(paddc); |
@@ -1190,25 +1006,26 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len | |||
1190 | } | 1006 | } |
1191 | name[ARPT_TABLE_MAXNAMELEN-1] = '\0'; | 1007 | name[ARPT_TABLE_MAXNAMELEN-1] = '\0'; |
1192 | 1008 | ||
1193 | t = try_then_request_module(find_table_lock(name), | 1009 | t = try_then_request_module(xt_find_table_lock(NF_ARP, name), |
1194 | "arptable_%s", name); | 1010 | "arptable_%s", name); |
1195 | if (t && !IS_ERR(t)) { | 1011 | if (t && !IS_ERR(t)) { |
1196 | struct arpt_getinfo info; | 1012 | struct arpt_getinfo info; |
1013 | struct xt_table_info *private = t->private; | ||
1197 | 1014 | ||
1198 | info.valid_hooks = t->valid_hooks; | 1015 | info.valid_hooks = t->valid_hooks; |
1199 | memcpy(info.hook_entry, t->private->hook_entry, | 1016 | memcpy(info.hook_entry, private->hook_entry, |
1200 | sizeof(info.hook_entry)); | 1017 | sizeof(info.hook_entry)); |
1201 | memcpy(info.underflow, t->private->underflow, | 1018 | memcpy(info.underflow, private->underflow, |
1202 | sizeof(info.underflow)); | 1019 | sizeof(info.underflow)); |
1203 | info.num_entries = t->private->number; | 1020 | info.num_entries = private->number; |
1204 | info.size = t->private->size; | 1021 | info.size = private->size; |
1205 | strcpy(info.name, name); | 1022 | strcpy(info.name, name); |
1206 | 1023 | ||
1207 | if (copy_to_user(user, &info, *len) != 0) | 1024 | if (copy_to_user(user, &info, *len) != 0) |
1208 | ret = -EFAULT; | 1025 | ret = -EFAULT; |
1209 | else | 1026 | else |
1210 | ret = 0; | 1027 | ret = 0; |
1211 | up(&arpt_mutex); | 1028 | xt_table_unlock(t); |
1212 | module_put(t->me); | 1029 | module_put(t->me); |
1213 | } else | 1030 | } else |
1214 | ret = t ? PTR_ERR(t) : -ENOENT; | 1031 | ret = t ? PTR_ERR(t) : -ENOENT; |
@@ -1233,7 +1050,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len | |||
1233 | } | 1050 | } |
1234 | 1051 | ||
1235 | case ARPT_SO_GET_REVISION_TARGET: { | 1052 | case ARPT_SO_GET_REVISION_TARGET: { |
1236 | struct arpt_get_revision rev; | 1053 | struct xt_get_revision rev; |
1237 | 1054 | ||
1238 | if (*len != sizeof(rev)) { | 1055 | if (*len != sizeof(rev)) { |
1239 | ret = -EINVAL; | 1056 | ret = -EINVAL; |
@@ -1244,8 +1061,8 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len | |||
1244 | break; | 1061 | break; |
1245 | } | 1062 | } |
1246 | 1063 | ||
1247 | try_then_request_module(find_revision(rev.name, rev.revision, | 1064 | try_then_request_module(xt_find_revision(NF_ARP, rev.name, |
1248 | target_revfn, &ret), | 1065 | rev.revision, 1, &ret), |
1249 | "arpt_%s", rev.name); | 1066 | "arpt_%s", rev.name); |
1250 | break; | 1067 | break; |
1251 | } | 1068 | } |
@@ -1258,38 +1075,16 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len | |||
1258 | return ret; | 1075 | return ret; |
1259 | } | 1076 | } |
1260 | 1077 | ||
1261 | /* Registration hooks for targets. */ | ||
1262 | int arpt_register_target(struct arpt_target *target) | ||
1263 | { | ||
1264 | int ret; | ||
1265 | |||
1266 | ret = down_interruptible(&arpt_mutex); | ||
1267 | if (ret != 0) | ||
1268 | return ret; | ||
1269 | |||
1270 | list_add(&target->list, &arpt_target); | ||
1271 | up(&arpt_mutex); | ||
1272 | |||
1273 | return ret; | ||
1274 | } | ||
1275 | |||
1276 | void arpt_unregister_target(struct arpt_target *target) | ||
1277 | { | ||
1278 | down(&arpt_mutex); | ||
1279 | LIST_DELETE(&arpt_target, target); | ||
1280 | up(&arpt_mutex); | ||
1281 | } | ||
1282 | |||
1283 | int arpt_register_table(struct arpt_table *table, | 1078 | int arpt_register_table(struct arpt_table *table, |
1284 | const struct arpt_replace *repl) | 1079 | const struct arpt_replace *repl) |
1285 | { | 1080 | { |
1286 | int ret; | 1081 | int ret; |
1287 | struct arpt_table_info *newinfo; | 1082 | struct xt_table_info *newinfo; |
1288 | static struct arpt_table_info bootstrap | 1083 | static struct xt_table_info bootstrap |
1289 | = { 0, 0, 0, { 0 }, { 0 }, { } }; | 1084 | = { 0, 0, 0, { 0 }, { 0 }, { } }; |
1290 | void *loc_cpu_entry; | 1085 | void *loc_cpu_entry; |
1291 | 1086 | ||
1292 | newinfo = alloc_table_info(repl->size); | 1087 | newinfo = xt_alloc_table_info(repl->size); |
1293 | if (!newinfo) { | 1088 | if (!newinfo) { |
1294 | ret = -ENOMEM; | 1089 | ret = -ENOMEM; |
1295 | return ret; | 1090 | return ret; |
@@ -1304,60 +1099,33 @@ int arpt_register_table(struct arpt_table *table, | |||
1304 | repl->num_entries, | 1099 | repl->num_entries, |
1305 | repl->hook_entry, | 1100 | repl->hook_entry, |
1306 | repl->underflow); | 1101 | repl->underflow); |
1102 | |||
1307 | duprintf("arpt_register_table: translate table gives %d\n", ret); | 1103 | duprintf("arpt_register_table: translate table gives %d\n", ret); |
1308 | if (ret != 0) { | 1104 | if (ret != 0) { |
1309 | free_table_info(newinfo); | 1105 | xt_free_table_info(newinfo); |
1310 | return ret; | 1106 | return ret; |
1311 | } | 1107 | } |
1312 | 1108 | ||
1313 | ret = down_interruptible(&arpt_mutex); | 1109 | if (xt_register_table(table, &bootstrap, newinfo) != 0) { |
1314 | if (ret != 0) { | 1110 | xt_free_table_info(newinfo); |
1315 | free_table_info(newinfo); | ||
1316 | return ret; | 1111 | return ret; |
1317 | } | 1112 | } |
1318 | 1113 | ||
1319 | /* Don't autoload: we'd eat our tail... */ | 1114 | return 0; |
1320 | if (list_named_find(&arpt_tables, table->name)) { | ||
1321 | ret = -EEXIST; | ||
1322 | goto free_unlock; | ||
1323 | } | ||
1324 | |||
1325 | /* Simplifies replace_table code. */ | ||
1326 | table->private = &bootstrap; | ||
1327 | if (!replace_table(table, 0, newinfo, &ret)) | ||
1328 | goto free_unlock; | ||
1329 | |||
1330 | duprintf("table->private->number = %u\n", | ||
1331 | table->private->number); | ||
1332 | |||
1333 | /* save number of initial entries */ | ||
1334 | table->private->initial_entries = table->private->number; | ||
1335 | |||
1336 | rwlock_init(&table->lock); | ||
1337 | list_prepend(&arpt_tables, table); | ||
1338 | |||
1339 | unlock: | ||
1340 | up(&arpt_mutex); | ||
1341 | return ret; | ||
1342 | |||
1343 | free_unlock: | ||
1344 | free_table_info(newinfo); | ||
1345 | goto unlock; | ||
1346 | } | 1115 | } |
1347 | 1116 | ||
1348 | void arpt_unregister_table(struct arpt_table *table) | 1117 | void arpt_unregister_table(struct arpt_table *table) |
1349 | { | 1118 | { |
1119 | struct xt_table_info *private; | ||
1350 | void *loc_cpu_entry; | 1120 | void *loc_cpu_entry; |
1351 | 1121 | ||
1352 | down(&arpt_mutex); | 1122 | private = xt_unregister_table(table); |
1353 | LIST_DELETE(&arpt_tables, table); | ||
1354 | up(&arpt_mutex); | ||
1355 | 1123 | ||
1356 | /* Decrease module usage counts and free resources */ | 1124 | /* Decrease module usage counts and free resources */ |
1357 | loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; | 1125 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
1358 | ARPT_ENTRY_ITERATE(loc_cpu_entry, table->private->size, | 1126 | ARPT_ENTRY_ITERATE(loc_cpu_entry, private->size, |
1359 | cleanup_entry, NULL); | 1127 | cleanup_entry, NULL); |
1360 | free_table_info(table->private); | 1128 | xt_free_table_info(private); |
1361 | } | 1129 | } |
1362 | 1130 | ||
1363 | /* The built-in targets: standard (NULL) and error. */ | 1131 | /* The built-in targets: standard (NULL) and error. */ |
@@ -1380,52 +1148,15 @@ static struct nf_sockopt_ops arpt_sockopts = { | |||
1380 | .get = do_arpt_get_ctl, | 1148 | .get = do_arpt_get_ctl, |
1381 | }; | 1149 | }; |
1382 | 1150 | ||
1383 | #ifdef CONFIG_PROC_FS | ||
1384 | static inline int print_name(const struct arpt_table *t, | ||
1385 | off_t start_offset, char *buffer, int length, | ||
1386 | off_t *pos, unsigned int *count) | ||
1387 | { | ||
1388 | if ((*count)++ >= start_offset) { | ||
1389 | unsigned int namelen; | ||
1390 | |||
1391 | namelen = sprintf(buffer + *pos, "%s\n", t->name); | ||
1392 | if (*pos + namelen > length) { | ||
1393 | /* Stop iterating */ | ||
1394 | return 1; | ||
1395 | } | ||
1396 | *pos += namelen; | ||
1397 | } | ||
1398 | return 0; | ||
1399 | } | ||
1400 | |||
1401 | static int arpt_get_tables(char *buffer, char **start, off_t offset, int length) | ||
1402 | { | ||
1403 | off_t pos = 0; | ||
1404 | unsigned int count = 0; | ||
1405 | |||
1406 | if (down_interruptible(&arpt_mutex) != 0) | ||
1407 | return 0; | ||
1408 | |||
1409 | LIST_FIND(&arpt_tables, print_name, struct arpt_table *, | ||
1410 | offset, buffer, length, &pos, &count); | ||
1411 | |||
1412 | up(&arpt_mutex); | ||
1413 | |||
1414 | /* `start' hack - see fs/proc/generic.c line ~105 */ | ||
1415 | *start=(char *)((unsigned long)count-offset); | ||
1416 | return pos; | ||
1417 | } | ||
1418 | #endif /*CONFIG_PROC_FS*/ | ||
1419 | |||
1420 | static int __init init(void) | 1151 | static int __init init(void) |
1421 | { | 1152 | { |
1422 | int ret; | 1153 | int ret; |
1423 | 1154 | ||
1155 | xt_proto_init(NF_ARP); | ||
1156 | |||
1424 | /* Noone else will be downing sem now, so we won't sleep */ | 1157 | /* Noone else will be downing sem now, so we won't sleep */ |
1425 | down(&arpt_mutex); | 1158 | xt_register_target(NF_ARP, &arpt_standard_target); |
1426 | list_append(&arpt_target, &arpt_standard_target); | 1159 | xt_register_target(NF_ARP, &arpt_error_target); |
1427 | list_append(&arpt_target, &arpt_error_target); | ||
1428 | up(&arpt_mutex); | ||
1429 | 1160 | ||
1430 | /* Register setsockopt */ | 1161 | /* Register setsockopt */ |
1431 | ret = nf_register_sockopt(&arpt_sockopts); | 1162 | ret = nf_register_sockopt(&arpt_sockopts); |
@@ -1434,19 +1165,6 @@ static int __init init(void) | |||
1434 | return ret; | 1165 | return ret; |
1435 | } | 1166 | } |
1436 | 1167 | ||
1437 | #ifdef CONFIG_PROC_FS | ||
1438 | { | ||
1439 | struct proc_dir_entry *proc; | ||
1440 | |||
1441 | proc = proc_net_create("arp_tables_names", 0, arpt_get_tables); | ||
1442 | if (!proc) { | ||
1443 | nf_unregister_sockopt(&arpt_sockopts); | ||
1444 | return -ENOMEM; | ||
1445 | } | ||
1446 | proc->owner = THIS_MODULE; | ||
1447 | } | ||
1448 | #endif | ||
1449 | |||
1450 | printk("arp_tables: (C) 2002 David S. Miller\n"); | 1168 | printk("arp_tables: (C) 2002 David S. Miller\n"); |
1451 | return 0; | 1169 | return 0; |
1452 | } | 1170 | } |
@@ -1454,16 +1172,12 @@ static int __init init(void) | |||
1454 | static void __exit fini(void) | 1172 | static void __exit fini(void) |
1455 | { | 1173 | { |
1456 | nf_unregister_sockopt(&arpt_sockopts); | 1174 | nf_unregister_sockopt(&arpt_sockopts); |
1457 | #ifdef CONFIG_PROC_FS | 1175 | xt_proto_fini(NF_ARP); |
1458 | proc_net_remove("arp_tables_names"); | ||
1459 | #endif | ||
1460 | } | 1176 | } |
1461 | 1177 | ||
1462 | EXPORT_SYMBOL(arpt_register_table); | 1178 | EXPORT_SYMBOL(arpt_register_table); |
1463 | EXPORT_SYMBOL(arpt_unregister_table); | 1179 | EXPORT_SYMBOL(arpt_unregister_table); |
1464 | EXPORT_SYMBOL(arpt_do_table); | 1180 | EXPORT_SYMBOL(arpt_do_table); |
1465 | EXPORT_SYMBOL(arpt_register_target); | ||
1466 | EXPORT_SYMBOL(arpt_unregister_target); | ||
1467 | 1181 | ||
1468 | module_init(init); | 1182 | module_init(init); |
1469 | module_exit(fini); | 1183 | module_exit(fini); |
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c index 3e592ec86482..c97650a16a5b 100644 --- a/net/ipv4/netfilter/arpt_mangle.c +++ b/net/ipv4/netfilter/arpt_mangle.c | |||
@@ -8,8 +8,9 @@ MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); | |||
8 | MODULE_DESCRIPTION("arptables arp payload mangle target"); | 8 | MODULE_DESCRIPTION("arptables arp payload mangle target"); |
9 | 9 | ||
10 | static unsigned int | 10 | static unsigned int |
11 | target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, | 11 | target(struct sk_buff **pskb, const struct net_device *in, |
12 | const struct net_device *out, const void *targinfo, void *userinfo) | 12 | const struct net_device *out, unsigned int hooknum, const void *targinfo, |
13 | void *userinfo) | ||
13 | { | 14 | { |
14 | const struct arpt_mangle *mangle = targinfo; | 15 | const struct arpt_mangle *mangle = targinfo; |
15 | struct arphdr *arp; | 16 | struct arphdr *arp; |
@@ -64,7 +65,7 @@ target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, | |||
64 | } | 65 | } |
65 | 66 | ||
66 | static int | 67 | static int |
67 | checkentry(const char *tablename, const struct arpt_entry *e, void *targinfo, | 68 | checkentry(const char *tablename, const void *e, void *targinfo, |
68 | unsigned int targinfosize, unsigned int hook_mask) | 69 | unsigned int targinfosize, unsigned int hook_mask) |
69 | { | 70 | { |
70 | const struct arpt_mangle *mangle = targinfo; | 71 | const struct arpt_mangle *mangle = targinfo; |
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index 0d759f5a4ef0..f6ab45f48681 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c | |||
@@ -145,6 +145,7 @@ static struct arpt_table packet_filter = { | |||
145 | .lock = RW_LOCK_UNLOCKED, | 145 | .lock = RW_LOCK_UNLOCKED, |
146 | .private = NULL, | 146 | .private = NULL, |
147 | .me = THIS_MODULE, | 147 | .me = THIS_MODULE, |
148 | .af = NF_ARP, | ||
148 | }; | 149 | }; |
149 | 150 | ||
150 | /* The work comes in here from netfilter.c */ | 151 | /* The work comes in here from netfilter.c */ |
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 9dec1293f67a..833fcb4be5e7 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c | |||
@@ -944,7 +944,7 @@ module_exit(fini); | |||
944 | 944 | ||
945 | /* Some modules need us, but don't depend directly on any symbol. | 945 | /* Some modules need us, but don't depend directly on any symbol. |
946 | They should call this. */ | 946 | They should call this. */ |
947 | void need_ip_conntrack(void) | 947 | void need_conntrack(void) |
948 | { | 948 | { |
949 | } | 949 | } |
950 | 950 | ||
@@ -962,7 +962,7 @@ EXPORT_SYMBOL(ip_ct_get_tuple); | |||
962 | EXPORT_SYMBOL(invert_tuplepr); | 962 | EXPORT_SYMBOL(invert_tuplepr); |
963 | EXPORT_SYMBOL(ip_conntrack_alter_reply); | 963 | EXPORT_SYMBOL(ip_conntrack_alter_reply); |
964 | EXPORT_SYMBOL(ip_conntrack_destroyed); | 964 | EXPORT_SYMBOL(ip_conntrack_destroyed); |
965 | EXPORT_SYMBOL(need_ip_conntrack); | 965 | EXPORT_SYMBOL(need_conntrack); |
966 | EXPORT_SYMBOL(ip_conntrack_helper_register); | 966 | EXPORT_SYMBOL(ip_conntrack_helper_register); |
967 | EXPORT_SYMBOL(ip_conntrack_helper_unregister); | 967 | EXPORT_SYMBOL(ip_conntrack_helper_unregister); |
968 | EXPORT_SYMBOL(ip_ct_iterate_cleanup); | 968 | EXPORT_SYMBOL(ip_ct_iterate_cleanup); |
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c index cb66b8bddeb3..1de86282d232 100644 --- a/net/ipv4/netfilter/ip_nat_rule.c +++ b/net/ipv4/netfilter/ip_nat_rule.c | |||
@@ -95,6 +95,7 @@ static struct ipt_table nat_table = { | |||
95 | .valid_hooks = NAT_VALID_HOOKS, | 95 | .valid_hooks = NAT_VALID_HOOKS, |
96 | .lock = RW_LOCK_UNLOCKED, | 96 | .lock = RW_LOCK_UNLOCKED, |
97 | .me = THIS_MODULE, | 97 | .me = THIS_MODULE, |
98 | .af = AF_INET, | ||
98 | }; | 99 | }; |
99 | 100 | ||
100 | /* Source NAT */ | 101 | /* Source NAT */ |
@@ -168,7 +169,7 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb, | |||
168 | } | 169 | } |
169 | 170 | ||
170 | static int ipt_snat_checkentry(const char *tablename, | 171 | static int ipt_snat_checkentry(const char *tablename, |
171 | const struct ipt_entry *e, | 172 | const void *entry, |
172 | void *targinfo, | 173 | void *targinfo, |
173 | unsigned int targinfosize, | 174 | unsigned int targinfosize, |
174 | unsigned int hook_mask) | 175 | unsigned int hook_mask) |
@@ -201,7 +202,7 @@ static int ipt_snat_checkentry(const char *tablename, | |||
201 | } | 202 | } |
202 | 203 | ||
203 | static int ipt_dnat_checkentry(const char *tablename, | 204 | static int ipt_dnat_checkentry(const char *tablename, |
204 | const struct ipt_entry *e, | 205 | const void *entry, |
205 | void *targinfo, | 206 | void *targinfo, |
206 | unsigned int targinfosize, | 207 | unsigned int targinfosize, |
207 | unsigned int hook_mask) | 208 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 8b8a1f00bbf4..ad438fb185b8 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c | |||
@@ -364,7 +364,7 @@ static int init_or_cleanup(int init) | |||
364 | { | 364 | { |
365 | int ret = 0; | 365 | int ret = 0; |
366 | 366 | ||
367 | need_ip_conntrack(); | 367 | need_conntrack(); |
368 | 368 | ||
369 | if (!init) goto cleanup; | 369 | if (!init) goto cleanup; |
370 | 370 | ||
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 877bc96d3336..2371b2062c2d 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Packet matching code. | 2 | * Packet matching code. |
3 | * | 3 | * |
4 | * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling | 4 | * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling |
5 | * Copyright (C) 2000-2004 Netfilter Core Team <coreteam@netfilter.org> | 5 | * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -11,6 +11,8 @@ | |||
11 | * 19 Jan 2002 Harald Welte <laforge@gnumonks.org> | 11 | * 19 Jan 2002 Harald Welte <laforge@gnumonks.org> |
12 | * - increase module usage count as soon as we have rules inside | 12 | * - increase module usage count as soon as we have rules inside |
13 | * a table | 13 | * a table |
14 | * 08 Oct 2005 Harald Welte <lafore@netfilter.org> | ||
15 | * - Generalize into "x_tables" layer and "{ip,ip6,arp}_tables" | ||
14 | */ | 16 | */ |
15 | #include <linux/config.h> | 17 | #include <linux/config.h> |
16 | #include <linux/cache.h> | 18 | #include <linux/cache.h> |
@@ -20,8 +22,6 @@ | |||
20 | #include <linux/vmalloc.h> | 22 | #include <linux/vmalloc.h> |
21 | #include <linux/netdevice.h> | 23 | #include <linux/netdevice.h> |
22 | #include <linux/module.h> | 24 | #include <linux/module.h> |
23 | #include <linux/tcp.h> | ||
24 | #include <linux/udp.h> | ||
25 | #include <linux/icmp.h> | 25 | #include <linux/icmp.h> |
26 | #include <net/ip.h> | 26 | #include <net/ip.h> |
27 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/err.h> | 30 | #include <linux/err.h> |
31 | #include <linux/cpumask.h> | 31 | #include <linux/cpumask.h> |
32 | 32 | ||
33 | #include <linux/netfilter/x_tables.h> | ||
33 | #include <linux/netfilter_ipv4/ip_tables.h> | 34 | #include <linux/netfilter_ipv4/ip_tables.h> |
34 | 35 | ||
35 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
@@ -62,14 +63,6 @@ do { \ | |||
62 | #else | 63 | #else |
63 | #define IP_NF_ASSERT(x) | 64 | #define IP_NF_ASSERT(x) |
64 | #endif | 65 | #endif |
65 | #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) | ||
66 | |||
67 | static DECLARE_MUTEX(ipt_mutex); | ||
68 | |||
69 | /* Must have mutex */ | ||
70 | #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0) | ||
71 | #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0) | ||
72 | #include <linux/netfilter_ipv4/listhelp.h> | ||
73 | 66 | ||
74 | #if 0 | 67 | #if 0 |
75 | /* All the better to debug you with... */ | 68 | /* All the better to debug you with... */ |
@@ -86,36 +79,6 @@ static DECLARE_MUTEX(ipt_mutex); | |||
86 | 79 | ||
87 | Hence the start of any table is given by get_table() below. */ | 80 | Hence the start of any table is given by get_table() below. */ |
88 | 81 | ||
89 | /* The table itself */ | ||
90 | struct ipt_table_info | ||
91 | { | ||
92 | /* Size per table */ | ||
93 | unsigned int size; | ||
94 | /* Number of entries: FIXME. --RR */ | ||
95 | unsigned int number; | ||
96 | /* Initial number of entries. Needed for module usage count */ | ||
97 | unsigned int initial_entries; | ||
98 | |||
99 | /* Entry points and underflows */ | ||
100 | unsigned int hook_entry[NF_IP_NUMHOOKS]; | ||
101 | unsigned int underflow[NF_IP_NUMHOOKS]; | ||
102 | |||
103 | /* ipt_entry tables: one per CPU */ | ||
104 | void *entries[NR_CPUS]; | ||
105 | }; | ||
106 | |||
107 | static LIST_HEAD(ipt_target); | ||
108 | static LIST_HEAD(ipt_match); | ||
109 | static LIST_HEAD(ipt_tables); | ||
110 | #define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) | ||
111 | #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) | ||
112 | |||
113 | #if 0 | ||
114 | #define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0) | ||
115 | #define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; }) | ||
116 | #define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0) | ||
117 | #endif | ||
118 | |||
119 | /* Returns whether matches rule or not. */ | 82 | /* Returns whether matches rule or not. */ |
120 | static inline int | 83 | static inline int |
121 | ip_packet_match(const struct iphdr *ip, | 84 | ip_packet_match(const struct iphdr *ip, |
@@ -234,7 +197,8 @@ int do_match(struct ipt_entry_match *m, | |||
234 | int *hotdrop) | 197 | int *hotdrop) |
235 | { | 198 | { |
236 | /* Stop iteration if it doesn't match */ | 199 | /* Stop iteration if it doesn't match */ |
237 | if (!m->u.kernel.match->match(skb, in, out, m->data, offset, hotdrop)) | 200 | if (!m->u.kernel.match->match(skb, in, out, m->data, offset, |
201 | skb->nh.iph->ihl*4, hotdrop)) | ||
238 | return 1; | 202 | return 1; |
239 | else | 203 | else |
240 | return 0; | 204 | return 0; |
@@ -265,6 +229,7 @@ ipt_do_table(struct sk_buff **pskb, | |||
265 | const char *indev, *outdev; | 229 | const char *indev, *outdev; |
266 | void *table_base; | 230 | void *table_base; |
267 | struct ipt_entry *e, *back; | 231 | struct ipt_entry *e, *back; |
232 | struct xt_table_info *private = table->private; | ||
268 | 233 | ||
269 | /* Initialization */ | 234 | /* Initialization */ |
270 | ip = (*pskb)->nh.iph; | 235 | ip = (*pskb)->nh.iph; |
@@ -281,24 +246,11 @@ ipt_do_table(struct sk_buff **pskb, | |||
281 | 246 | ||
282 | read_lock_bh(&table->lock); | 247 | read_lock_bh(&table->lock); |
283 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | 248 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
284 | table_base = (void *)table->private->entries[smp_processor_id()]; | 249 | table_base = (void *)private->entries[smp_processor_id()]; |
285 | e = get_entry(table_base, table->private->hook_entry[hook]); | 250 | e = get_entry(table_base, private->hook_entry[hook]); |
286 | |||
287 | #ifdef CONFIG_NETFILTER_DEBUG | ||
288 | /* Check noone else using our table */ | ||
289 | if (((struct ipt_entry *)table_base)->comefrom != 0xdead57ac | ||
290 | && ((struct ipt_entry *)table_base)->comefrom != 0xeeeeeeec) { | ||
291 | printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n", | ||
292 | smp_processor_id(), | ||
293 | table->name, | ||
294 | &((struct ipt_entry *)table_base)->comefrom, | ||
295 | ((struct ipt_entry *)table_base)->comefrom); | ||
296 | } | ||
297 | ((struct ipt_entry *)table_base)->comefrom = 0x57acc001; | ||
298 | #endif | ||
299 | 251 | ||
300 | /* For return from builtin chain */ | 252 | /* For return from builtin chain */ |
301 | back = get_entry(table_base, table->private->underflow[hook]); | 253 | back = get_entry(table_base, private->underflow[hook]); |
302 | 254 | ||
303 | do { | 255 | do { |
304 | IP_NF_ASSERT(e); | 256 | IP_NF_ASSERT(e); |
@@ -384,9 +336,6 @@ ipt_do_table(struct sk_buff **pskb, | |||
384 | } | 336 | } |
385 | } while (!hotdrop); | 337 | } while (!hotdrop); |
386 | 338 | ||
387 | #ifdef CONFIG_NETFILTER_DEBUG | ||
388 | ((struct ipt_entry *)table_base)->comefrom = 0xdead57ac; | ||
389 | #endif | ||
390 | read_unlock_bh(&table->lock); | 339 | read_unlock_bh(&table->lock); |
391 | 340 | ||
392 | #ifdef DEBUG_ALLOW_ALL | 341 | #ifdef DEBUG_ALLOW_ALL |
@@ -398,145 +347,6 @@ ipt_do_table(struct sk_buff **pskb, | |||
398 | #endif | 347 | #endif |
399 | } | 348 | } |
400 | 349 | ||
401 | /* | ||
402 | * These are weird, but module loading must not be done with mutex | ||
403 | * held (since they will register), and we have to have a single | ||
404 | * function to use try_then_request_module(). | ||
405 | */ | ||
406 | |||
407 | /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ | ||
408 | static inline struct ipt_table *find_table_lock(const char *name) | ||
409 | { | ||
410 | struct ipt_table *t; | ||
411 | |||
412 | if (down_interruptible(&ipt_mutex) != 0) | ||
413 | return ERR_PTR(-EINTR); | ||
414 | |||
415 | list_for_each_entry(t, &ipt_tables, list) | ||
416 | if (strcmp(t->name, name) == 0 && try_module_get(t->me)) | ||
417 | return t; | ||
418 | up(&ipt_mutex); | ||
419 | return NULL; | ||
420 | } | ||
421 | |||
422 | /* Find match, grabs ref. Returns ERR_PTR() on error. */ | ||
423 | static inline struct ipt_match *find_match(const char *name, u8 revision) | ||
424 | { | ||
425 | struct ipt_match *m; | ||
426 | int err = 0; | ||
427 | |||
428 | if (down_interruptible(&ipt_mutex) != 0) | ||
429 | return ERR_PTR(-EINTR); | ||
430 | |||
431 | list_for_each_entry(m, &ipt_match, list) { | ||
432 | if (strcmp(m->name, name) == 0) { | ||
433 | if (m->revision == revision) { | ||
434 | if (try_module_get(m->me)) { | ||
435 | up(&ipt_mutex); | ||
436 | return m; | ||
437 | } | ||
438 | } else | ||
439 | err = -EPROTOTYPE; /* Found something. */ | ||
440 | } | ||
441 | } | ||
442 | up(&ipt_mutex); | ||
443 | return ERR_PTR(err); | ||
444 | } | ||
445 | |||
446 | /* Find target, grabs ref. Returns ERR_PTR() on error. */ | ||
447 | static inline struct ipt_target *find_target(const char *name, u8 revision) | ||
448 | { | ||
449 | struct ipt_target *t; | ||
450 | int err = 0; | ||
451 | |||
452 | if (down_interruptible(&ipt_mutex) != 0) | ||
453 | return ERR_PTR(-EINTR); | ||
454 | |||
455 | list_for_each_entry(t, &ipt_target, list) { | ||
456 | if (strcmp(t->name, name) == 0) { | ||
457 | if (t->revision == revision) { | ||
458 | if (try_module_get(t->me)) { | ||
459 | up(&ipt_mutex); | ||
460 | return t; | ||
461 | } | ||
462 | } else | ||
463 | err = -EPROTOTYPE; /* Found something. */ | ||
464 | } | ||
465 | } | ||
466 | up(&ipt_mutex); | ||
467 | return ERR_PTR(err); | ||
468 | } | ||
469 | |||
470 | struct ipt_target *ipt_find_target(const char *name, u8 revision) | ||
471 | { | ||
472 | struct ipt_target *target; | ||
473 | |||
474 | target = try_then_request_module(find_target(name, revision), | ||
475 | "ipt_%s", name); | ||
476 | if (IS_ERR(target) || !target) | ||
477 | return NULL; | ||
478 | return target; | ||
479 | } | ||
480 | |||
481 | static int match_revfn(const char *name, u8 revision, int *bestp) | ||
482 | { | ||
483 | struct ipt_match *m; | ||
484 | int have_rev = 0; | ||
485 | |||
486 | list_for_each_entry(m, &ipt_match, list) { | ||
487 | if (strcmp(m->name, name) == 0) { | ||
488 | if (m->revision > *bestp) | ||
489 | *bestp = m->revision; | ||
490 | if (m->revision == revision) | ||
491 | have_rev = 1; | ||
492 | } | ||
493 | } | ||
494 | return have_rev; | ||
495 | } | ||
496 | |||
497 | static int target_revfn(const char *name, u8 revision, int *bestp) | ||
498 | { | ||
499 | struct ipt_target *t; | ||
500 | int have_rev = 0; | ||
501 | |||
502 | list_for_each_entry(t, &ipt_target, list) { | ||
503 | if (strcmp(t->name, name) == 0) { | ||
504 | if (t->revision > *bestp) | ||
505 | *bestp = t->revision; | ||
506 | if (t->revision == revision) | ||
507 | have_rev = 1; | ||
508 | } | ||
509 | } | ||
510 | return have_rev; | ||
511 | } | ||
512 | |||
513 | /* Returns true or false (if no such extension at all) */ | ||
514 | static inline int find_revision(const char *name, u8 revision, | ||
515 | int (*revfn)(const char *, u8, int *), | ||
516 | int *err) | ||
517 | { | ||
518 | int have_rev, best = -1; | ||
519 | |||
520 | if (down_interruptible(&ipt_mutex) != 0) { | ||
521 | *err = -EINTR; | ||
522 | return 1; | ||
523 | } | ||
524 | have_rev = revfn(name, revision, &best); | ||
525 | up(&ipt_mutex); | ||
526 | |||
527 | /* Nothing at all? Return 0 to try loading module. */ | ||
528 | if (best == -1) { | ||
529 | *err = -ENOENT; | ||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | *err = best; | ||
534 | if (!have_rev) | ||
535 | *err = -EPROTONOSUPPORT; | ||
536 | return 1; | ||
537 | } | ||
538 | |||
539 | |||
540 | /* All zeroes == unconditional rule. */ | 350 | /* All zeroes == unconditional rule. */ |
541 | static inline int | 351 | static inline int |
542 | unconditional(const struct ipt_ip *ip) | 352 | unconditional(const struct ipt_ip *ip) |
@@ -553,7 +363,7 @@ unconditional(const struct ipt_ip *ip) | |||
553 | /* Figures out from what hook each rule can be called: returns 0 if | 363 | /* Figures out from what hook each rule can be called: returns 0 if |
554 | there are loops. Puts hook bitmask in comefrom. */ | 364 | there are loops. Puts hook bitmask in comefrom. */ |
555 | static int | 365 | static int |
556 | mark_source_chains(struct ipt_table_info *newinfo, | 366 | mark_source_chains(struct xt_table_info *newinfo, |
557 | unsigned int valid_hooks, void *entry0) | 367 | unsigned int valid_hooks, void *entry0) |
558 | { | 368 | { |
559 | unsigned int hook; | 369 | unsigned int hook; |
@@ -699,7 +509,7 @@ check_match(struct ipt_entry_match *m, | |||
699 | { | 509 | { |
700 | struct ipt_match *match; | 510 | struct ipt_match *match; |
701 | 511 | ||
702 | match = try_then_request_module(find_match(m->u.user.name, | 512 | match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name, |
703 | m->u.user.revision), | 513 | m->u.user.revision), |
704 | "ipt_%s", m->u.user.name); | 514 | "ipt_%s", m->u.user.name); |
705 | if (IS_ERR(match) || !match) { | 515 | if (IS_ERR(match) || !match) { |
@@ -744,7 +554,8 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, | |||
744 | goto cleanup_matches; | 554 | goto cleanup_matches; |
745 | 555 | ||
746 | t = ipt_get_target(e); | 556 | t = ipt_get_target(e); |
747 | target = try_then_request_module(find_target(t->u.user.name, | 557 | target = try_then_request_module(xt_find_target(AF_INET, |
558 | t->u.user.name, | ||
748 | t->u.user.revision), | 559 | t->u.user.revision), |
749 | "ipt_%s", t->u.user.name); | 560 | "ipt_%s", t->u.user.name); |
750 | if (IS_ERR(target) || !target) { | 561 | if (IS_ERR(target) || !target) { |
@@ -781,7 +592,7 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, | |||
781 | 592 | ||
782 | static inline int | 593 | static inline int |
783 | check_entry_size_and_hooks(struct ipt_entry *e, | 594 | check_entry_size_and_hooks(struct ipt_entry *e, |
784 | struct ipt_table_info *newinfo, | 595 | struct xt_table_info *newinfo, |
785 | unsigned char *base, | 596 | unsigned char *base, |
786 | unsigned char *limit, | 597 | unsigned char *limit, |
787 | const unsigned int *hook_entries, | 598 | const unsigned int *hook_entries, |
@@ -815,7 +626,7 @@ check_entry_size_and_hooks(struct ipt_entry *e, | |||
815 | < 0 (not IPT_RETURN). --RR */ | 626 | < 0 (not IPT_RETURN). --RR */ |
816 | 627 | ||
817 | /* Clear counters and comefrom */ | 628 | /* Clear counters and comefrom */ |
818 | e->counters = ((struct ipt_counters) { 0, 0 }); | 629 | e->counters = ((struct xt_counters) { 0, 0 }); |
819 | e->comefrom = 0; | 630 | e->comefrom = 0; |
820 | 631 | ||
821 | (*i)++; | 632 | (*i)++; |
@@ -845,7 +656,7 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i) | |||
845 | static int | 656 | static int |
846 | translate_table(const char *name, | 657 | translate_table(const char *name, |
847 | unsigned int valid_hooks, | 658 | unsigned int valid_hooks, |
848 | struct ipt_table_info *newinfo, | 659 | struct xt_table_info *newinfo, |
849 | void *entry0, | 660 | void *entry0, |
850 | unsigned int size, | 661 | unsigned int size, |
851 | unsigned int number, | 662 | unsigned int number, |
@@ -922,48 +733,10 @@ translate_table(const char *name, | |||
922 | return ret; | 733 | return ret; |
923 | } | 734 | } |
924 | 735 | ||
925 | static struct ipt_table_info * | ||
926 | replace_table(struct ipt_table *table, | ||
927 | unsigned int num_counters, | ||
928 | struct ipt_table_info *newinfo, | ||
929 | int *error) | ||
930 | { | ||
931 | struct ipt_table_info *oldinfo; | ||
932 | |||
933 | #ifdef CONFIG_NETFILTER_DEBUG | ||
934 | { | ||
935 | int cpu; | ||
936 | |||
937 | for_each_cpu(cpu) { | ||
938 | struct ipt_entry *table_base = newinfo->entries[cpu]; | ||
939 | if (table_base) | ||
940 | table_base->comefrom = 0xdead57ac; | ||
941 | } | ||
942 | } | ||
943 | #endif | ||
944 | |||
945 | /* Do the substitution. */ | ||
946 | write_lock_bh(&table->lock); | ||
947 | /* Check inside lock: is the old number correct? */ | ||
948 | if (num_counters != table->private->number) { | ||
949 | duprintf("num_counters != table->private->number (%u/%u)\n", | ||
950 | num_counters, table->private->number); | ||
951 | write_unlock_bh(&table->lock); | ||
952 | *error = -EAGAIN; | ||
953 | return NULL; | ||
954 | } | ||
955 | oldinfo = table->private; | ||
956 | table->private = newinfo; | ||
957 | newinfo->initial_entries = oldinfo->initial_entries; | ||
958 | write_unlock_bh(&table->lock); | ||
959 | |||
960 | return oldinfo; | ||
961 | } | ||
962 | |||
963 | /* Gets counters. */ | 736 | /* Gets counters. */ |
964 | static inline int | 737 | static inline int |
965 | add_entry_to_counter(const struct ipt_entry *e, | 738 | add_entry_to_counter(const struct ipt_entry *e, |
966 | struct ipt_counters total[], | 739 | struct xt_counters total[], |
967 | unsigned int *i) | 740 | unsigned int *i) |
968 | { | 741 | { |
969 | ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); | 742 | ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); |
@@ -984,8 +757,8 @@ set_entry_to_counter(const struct ipt_entry *e, | |||
984 | } | 757 | } |
985 | 758 | ||
986 | static void | 759 | static void |
987 | get_counters(const struct ipt_table_info *t, | 760 | get_counters(const struct xt_table_info *t, |
988 | struct ipt_counters counters[]) | 761 | struct xt_counters counters[]) |
989 | { | 762 | { |
990 | unsigned int cpu; | 763 | unsigned int cpu; |
991 | unsigned int i; | 764 | unsigned int i; |
@@ -1024,14 +797,15 @@ copy_entries_to_user(unsigned int total_size, | |||
1024 | { | 797 | { |
1025 | unsigned int off, num, countersize; | 798 | unsigned int off, num, countersize; |
1026 | struct ipt_entry *e; | 799 | struct ipt_entry *e; |
1027 | struct ipt_counters *counters; | 800 | struct xt_counters *counters; |
801 | struct xt_table_info *private = table->private; | ||
1028 | int ret = 0; | 802 | int ret = 0; |
1029 | void *loc_cpu_entry; | 803 | void *loc_cpu_entry; |
1030 | 804 | ||
1031 | /* We need atomic snapshot of counters: rest doesn't change | 805 | /* We need atomic snapshot of counters: rest doesn't change |
1032 | (other than comefrom, which userspace doesn't care | 806 | (other than comefrom, which userspace doesn't care |
1033 | about). */ | 807 | about). */ |
1034 | countersize = sizeof(struct ipt_counters) * table->private->number; | 808 | countersize = sizeof(struct xt_counters) * private->number; |
1035 | counters = vmalloc_node(countersize, numa_node_id()); | 809 | counters = vmalloc_node(countersize, numa_node_id()); |
1036 | 810 | ||
1037 | if (counters == NULL) | 811 | if (counters == NULL) |
@@ -1039,14 +813,14 @@ copy_entries_to_user(unsigned int total_size, | |||
1039 | 813 | ||
1040 | /* First, sum counters... */ | 814 | /* First, sum counters... */ |
1041 | write_lock_bh(&table->lock); | 815 | write_lock_bh(&table->lock); |
1042 | get_counters(table->private, counters); | 816 | get_counters(private, counters); |
1043 | write_unlock_bh(&table->lock); | 817 | write_unlock_bh(&table->lock); |
1044 | 818 | ||
1045 | /* choose the copy that is on our node/cpu, ... | 819 | /* choose the copy that is on our node/cpu, ... |
1046 | * This choice is lazy (because current thread is | 820 | * This choice is lazy (because current thread is |
1047 | * allowed to migrate to another cpu) | 821 | * allowed to migrate to another cpu) |
1048 | */ | 822 | */ |
1049 | loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; | 823 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
1050 | /* ... then copy entire thing ... */ | 824 | /* ... then copy entire thing ... */ |
1051 | if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { | 825 | if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { |
1052 | ret = -EFAULT; | 826 | ret = -EFAULT; |
@@ -1108,74 +882,36 @@ get_entries(const struct ipt_get_entries *entries, | |||
1108 | int ret; | 882 | int ret; |
1109 | struct ipt_table *t; | 883 | struct ipt_table *t; |
1110 | 884 | ||
1111 | t = find_table_lock(entries->name); | 885 | t = xt_find_table_lock(AF_INET, entries->name); |
1112 | if (t && !IS_ERR(t)) { | 886 | if (t && !IS_ERR(t)) { |
887 | struct xt_table_info *private = t->private; | ||
1113 | duprintf("t->private->number = %u\n", | 888 | duprintf("t->private->number = %u\n", |
1114 | t->private->number); | 889 | private->number); |
1115 | if (entries->size == t->private->size) | 890 | if (entries->size == private->size) |
1116 | ret = copy_entries_to_user(t->private->size, | 891 | ret = copy_entries_to_user(private->size, |
1117 | t, uptr->entrytable); | 892 | t, uptr->entrytable); |
1118 | else { | 893 | else { |
1119 | duprintf("get_entries: I've got %u not %u!\n", | 894 | duprintf("get_entries: I've got %u not %u!\n", |
1120 | t->private->size, | 895 | private->size, |
1121 | entries->size); | 896 | entries->size); |
1122 | ret = -EINVAL; | 897 | ret = -EINVAL; |
1123 | } | 898 | } |
1124 | module_put(t->me); | 899 | module_put(t->me); |
1125 | up(&ipt_mutex); | 900 | xt_table_unlock(t); |
1126 | } else | 901 | } else |
1127 | ret = t ? PTR_ERR(t) : -ENOENT; | 902 | ret = t ? PTR_ERR(t) : -ENOENT; |
1128 | 903 | ||
1129 | return ret; | 904 | return ret; |
1130 | } | 905 | } |
1131 | 906 | ||
1132 | static void free_table_info(struct ipt_table_info *info) | ||
1133 | { | ||
1134 | int cpu; | ||
1135 | for_each_cpu(cpu) { | ||
1136 | if (info->size <= PAGE_SIZE) | ||
1137 | kfree(info->entries[cpu]); | ||
1138 | else | ||
1139 | vfree(info->entries[cpu]); | ||
1140 | } | ||
1141 | kfree(info); | ||
1142 | } | ||
1143 | |||
1144 | static struct ipt_table_info *alloc_table_info(unsigned int size) | ||
1145 | { | ||
1146 | struct ipt_table_info *newinfo; | ||
1147 | int cpu; | ||
1148 | |||
1149 | newinfo = kzalloc(sizeof(struct ipt_table_info), GFP_KERNEL); | ||
1150 | if (!newinfo) | ||
1151 | return NULL; | ||
1152 | |||
1153 | newinfo->size = size; | ||
1154 | |||
1155 | for_each_cpu(cpu) { | ||
1156 | if (size <= PAGE_SIZE) | ||
1157 | newinfo->entries[cpu] = kmalloc_node(size, | ||
1158 | GFP_KERNEL, | ||
1159 | cpu_to_node(cpu)); | ||
1160 | else | ||
1161 | newinfo->entries[cpu] = vmalloc_node(size, cpu_to_node(cpu)); | ||
1162 | if (newinfo->entries[cpu] == 0) { | ||
1163 | free_table_info(newinfo); | ||
1164 | return NULL; | ||
1165 | } | ||
1166 | } | ||
1167 | |||
1168 | return newinfo; | ||
1169 | } | ||
1170 | |||
1171 | static int | 907 | static int |
1172 | do_replace(void __user *user, unsigned int len) | 908 | do_replace(void __user *user, unsigned int len) |
1173 | { | 909 | { |
1174 | int ret; | 910 | int ret; |
1175 | struct ipt_replace tmp; | 911 | struct ipt_replace tmp; |
1176 | struct ipt_table *t; | 912 | struct ipt_table *t; |
1177 | struct ipt_table_info *newinfo, *oldinfo; | 913 | struct xt_table_info *newinfo, *oldinfo; |
1178 | struct ipt_counters *counters; | 914 | struct xt_counters *counters; |
1179 | void *loc_cpu_entry, *loc_cpu_old_entry; | 915 | void *loc_cpu_entry, *loc_cpu_old_entry; |
1180 | 916 | ||
1181 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) | 917 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) |
@@ -1185,11 +921,7 @@ do_replace(void __user *user, unsigned int len) | |||
1185 | if (len != sizeof(tmp) + tmp.size) | 921 | if (len != sizeof(tmp) + tmp.size) |
1186 | return -ENOPROTOOPT; | 922 | return -ENOPROTOOPT; |
1187 | 923 | ||
1188 | /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ | 924 | newinfo = xt_alloc_table_info(tmp.size); |
1189 | if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages) | ||
1190 | return -ENOMEM; | ||
1191 | |||
1192 | newinfo = alloc_table_info(tmp.size); | ||
1193 | if (!newinfo) | 925 | if (!newinfo) |
1194 | return -ENOMEM; | 926 | return -ENOMEM; |
1195 | 927 | ||
@@ -1201,7 +933,7 @@ do_replace(void __user *user, unsigned int len) | |||
1201 | goto free_newinfo; | 933 | goto free_newinfo; |
1202 | } | 934 | } |
1203 | 935 | ||
1204 | counters = vmalloc(tmp.num_counters * sizeof(struct ipt_counters)); | 936 | counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters)); |
1205 | if (!counters) { | 937 | if (!counters) { |
1206 | ret = -ENOMEM; | 938 | ret = -ENOMEM; |
1207 | goto free_newinfo; | 939 | goto free_newinfo; |
@@ -1215,7 +947,7 @@ do_replace(void __user *user, unsigned int len) | |||
1215 | 947 | ||
1216 | duprintf("ip_tables: Translated table\n"); | 948 | duprintf("ip_tables: Translated table\n"); |
1217 | 949 | ||
1218 | t = try_then_request_module(find_table_lock(tmp.name), | 950 | t = try_then_request_module(xt_find_table_lock(AF_INET, tmp.name), |
1219 | "iptable_%s", tmp.name); | 951 | "iptable_%s", tmp.name); |
1220 | if (!t || IS_ERR(t)) { | 952 | if (!t || IS_ERR(t)) { |
1221 | ret = t ? PTR_ERR(t) : -ENOENT; | 953 | ret = t ? PTR_ERR(t) : -ENOENT; |
@@ -1230,7 +962,7 @@ do_replace(void __user *user, unsigned int len) | |||
1230 | goto put_module; | 962 | goto put_module; |
1231 | } | 963 | } |
1232 | 964 | ||
1233 | oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); | 965 | oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret); |
1234 | if (!oldinfo) | 966 | if (!oldinfo) |
1235 | goto put_module; | 967 | goto put_module; |
1236 | 968 | ||
@@ -1249,23 +981,23 @@ do_replace(void __user *user, unsigned int len) | |||
1249 | /* Decrease module usage counts and free resource */ | 981 | /* Decrease module usage counts and free resource */ |
1250 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; | 982 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; |
1251 | IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); | 983 | IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); |
1252 | free_table_info(oldinfo); | 984 | xt_free_table_info(oldinfo); |
1253 | if (copy_to_user(tmp.counters, counters, | 985 | if (copy_to_user(tmp.counters, counters, |
1254 | sizeof(struct ipt_counters) * tmp.num_counters) != 0) | 986 | sizeof(struct xt_counters) * tmp.num_counters) != 0) |
1255 | ret = -EFAULT; | 987 | ret = -EFAULT; |
1256 | vfree(counters); | 988 | vfree(counters); |
1257 | up(&ipt_mutex); | 989 | xt_table_unlock(t); |
1258 | return ret; | 990 | return ret; |
1259 | 991 | ||
1260 | put_module: | 992 | put_module: |
1261 | module_put(t->me); | 993 | module_put(t->me); |
1262 | up(&ipt_mutex); | 994 | xt_table_unlock(t); |
1263 | free_newinfo_counters_untrans: | 995 | free_newinfo_counters_untrans: |
1264 | IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); | 996 | IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); |
1265 | free_newinfo_counters: | 997 | free_newinfo_counters: |
1266 | vfree(counters); | 998 | vfree(counters); |
1267 | free_newinfo: | 999 | free_newinfo: |
1268 | free_table_info(newinfo); | 1000 | xt_free_table_info(newinfo); |
1269 | return ret; | 1001 | return ret; |
1270 | } | 1002 | } |
1271 | 1003 | ||
@@ -1273,7 +1005,7 @@ do_replace(void __user *user, unsigned int len) | |||
1273 | * and everything is OK. */ | 1005 | * and everything is OK. */ |
1274 | static inline int | 1006 | static inline int |
1275 | add_counter_to_entry(struct ipt_entry *e, | 1007 | add_counter_to_entry(struct ipt_entry *e, |
1276 | const struct ipt_counters addme[], | 1008 | const struct xt_counters addme[], |
1277 | unsigned int *i) | 1009 | unsigned int *i) |
1278 | { | 1010 | { |
1279 | #if 0 | 1011 | #if 0 |
@@ -1295,15 +1027,16 @@ static int | |||
1295 | do_add_counters(void __user *user, unsigned int len) | 1027 | do_add_counters(void __user *user, unsigned int len) |
1296 | { | 1028 | { |
1297 | unsigned int i; | 1029 | unsigned int i; |
1298 | struct ipt_counters_info tmp, *paddc; | 1030 | struct xt_counters_info tmp, *paddc; |
1299 | struct ipt_table *t; | 1031 | struct ipt_table *t; |
1032 | struct xt_table_info *private; | ||
1300 | int ret = 0; | 1033 | int ret = 0; |
1301 | void *loc_cpu_entry; | 1034 | void *loc_cpu_entry; |
1302 | 1035 | ||
1303 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) | 1036 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) |
1304 | return -EFAULT; | 1037 | return -EFAULT; |
1305 | 1038 | ||
1306 | if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ipt_counters)) | 1039 | if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters)) |
1307 | return -EINVAL; | 1040 | return -EINVAL; |
1308 | 1041 | ||
1309 | paddc = vmalloc_node(len, numa_node_id()); | 1042 | paddc = vmalloc_node(len, numa_node_id()); |
@@ -1315,29 +1048,30 @@ do_add_counters(void __user *user, unsigned int len) | |||
1315 | goto free; | 1048 | goto free; |
1316 | } | 1049 | } |
1317 | 1050 | ||
1318 | t = find_table_lock(tmp.name); | 1051 | t = xt_find_table_lock(AF_INET, tmp.name); |
1319 | if (!t || IS_ERR(t)) { | 1052 | if (!t || IS_ERR(t)) { |
1320 | ret = t ? PTR_ERR(t) : -ENOENT; | 1053 | ret = t ? PTR_ERR(t) : -ENOENT; |
1321 | goto free; | 1054 | goto free; |
1322 | } | 1055 | } |
1323 | 1056 | ||
1324 | write_lock_bh(&t->lock); | 1057 | write_lock_bh(&t->lock); |
1325 | if (t->private->number != paddc->num_counters) { | 1058 | private = t->private; |
1059 | if (private->number != paddc->num_counters) { | ||
1326 | ret = -EINVAL; | 1060 | ret = -EINVAL; |
1327 | goto unlock_up_free; | 1061 | goto unlock_up_free; |
1328 | } | 1062 | } |
1329 | 1063 | ||
1330 | i = 0; | 1064 | i = 0; |
1331 | /* Choose the copy that is on our node */ | 1065 | /* Choose the copy that is on our node */ |
1332 | loc_cpu_entry = t->private->entries[raw_smp_processor_id()]; | 1066 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
1333 | IPT_ENTRY_ITERATE(loc_cpu_entry, | 1067 | IPT_ENTRY_ITERATE(loc_cpu_entry, |
1334 | t->private->size, | 1068 | private->size, |
1335 | add_counter_to_entry, | 1069 | add_counter_to_entry, |
1336 | paddc->counters, | 1070 | paddc->counters, |
1337 | &i); | 1071 | &i); |
1338 | unlock_up_free: | 1072 | unlock_up_free: |
1339 | write_unlock_bh(&t->lock); | 1073 | write_unlock_bh(&t->lock); |
1340 | up(&ipt_mutex); | 1074 | xt_table_unlock(t); |
1341 | module_put(t->me); | 1075 | module_put(t->me); |
1342 | free: | 1076 | free: |
1343 | vfree(paddc); | 1077 | vfree(paddc); |
@@ -1396,25 +1130,26 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1396 | } | 1130 | } |
1397 | name[IPT_TABLE_MAXNAMELEN-1] = '\0'; | 1131 | name[IPT_TABLE_MAXNAMELEN-1] = '\0'; |
1398 | 1132 | ||
1399 | t = try_then_request_module(find_table_lock(name), | 1133 | t = try_then_request_module(xt_find_table_lock(AF_INET, name), |
1400 | "iptable_%s", name); | 1134 | "iptable_%s", name); |
1401 | if (t && !IS_ERR(t)) { | 1135 | if (t && !IS_ERR(t)) { |
1402 | struct ipt_getinfo info; | 1136 | struct ipt_getinfo info; |
1137 | struct xt_table_info *private = t->private; | ||
1403 | 1138 | ||
1404 | info.valid_hooks = t->valid_hooks; | 1139 | info.valid_hooks = t->valid_hooks; |
1405 | memcpy(info.hook_entry, t->private->hook_entry, | 1140 | memcpy(info.hook_entry, private->hook_entry, |
1406 | sizeof(info.hook_entry)); | 1141 | sizeof(info.hook_entry)); |
1407 | memcpy(info.underflow, t->private->underflow, | 1142 | memcpy(info.underflow, private->underflow, |
1408 | sizeof(info.underflow)); | 1143 | sizeof(info.underflow)); |
1409 | info.num_entries = t->private->number; | 1144 | info.num_entries = private->number; |
1410 | info.size = t->private->size; | 1145 | info.size = private->size; |
1411 | memcpy(info.name, name, sizeof(info.name)); | 1146 | memcpy(info.name, name, sizeof(info.name)); |
1412 | 1147 | ||
1413 | if (copy_to_user(user, &info, *len) != 0) | 1148 | if (copy_to_user(user, &info, *len) != 0) |
1414 | ret = -EFAULT; | 1149 | ret = -EFAULT; |
1415 | else | 1150 | else |
1416 | ret = 0; | 1151 | ret = 0; |
1417 | up(&ipt_mutex); | 1152 | xt_table_unlock(t); |
1418 | module_put(t->me); | 1153 | module_put(t->me); |
1419 | } else | 1154 | } else |
1420 | ret = t ? PTR_ERR(t) : -ENOENT; | 1155 | ret = t ? PTR_ERR(t) : -ENOENT; |
@@ -1441,7 +1176,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1441 | case IPT_SO_GET_REVISION_MATCH: | 1176 | case IPT_SO_GET_REVISION_MATCH: |
1442 | case IPT_SO_GET_REVISION_TARGET: { | 1177 | case IPT_SO_GET_REVISION_TARGET: { |
1443 | struct ipt_get_revision rev; | 1178 | struct ipt_get_revision rev; |
1444 | int (*revfn)(const char *, u8, int *); | 1179 | int target; |
1445 | 1180 | ||
1446 | if (*len != sizeof(rev)) { | 1181 | if (*len != sizeof(rev)) { |
1447 | ret = -EINVAL; | 1182 | ret = -EINVAL; |
@@ -1453,12 +1188,13 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1453 | } | 1188 | } |
1454 | 1189 | ||
1455 | if (cmd == IPT_SO_GET_REVISION_TARGET) | 1190 | if (cmd == IPT_SO_GET_REVISION_TARGET) |
1456 | revfn = target_revfn; | 1191 | target = 1; |
1457 | else | 1192 | else |
1458 | revfn = match_revfn; | 1193 | target = 0; |
1459 | 1194 | ||
1460 | try_then_request_module(find_revision(rev.name, rev.revision, | 1195 | try_then_request_module(xt_find_revision(AF_INET, rev.name, |
1461 | revfn, &ret), | 1196 | rev.revision, |
1197 | target, &ret), | ||
1462 | "ipt_%s", rev.name); | 1198 | "ipt_%s", rev.name); |
1463 | break; | 1199 | break; |
1464 | } | 1200 | } |
@@ -1471,60 +1207,15 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1471 | return ret; | 1207 | return ret; |
1472 | } | 1208 | } |
1473 | 1209 | ||
1474 | /* Registration hooks for targets. */ | 1210 | int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl) |
1475 | int | ||
1476 | ipt_register_target(struct ipt_target *target) | ||
1477 | { | 1211 | { |
1478 | int ret; | 1212 | int ret; |
1479 | 1213 | struct xt_table_info *newinfo; | |
1480 | ret = down_interruptible(&ipt_mutex); | 1214 | static struct xt_table_info bootstrap |
1481 | if (ret != 0) | ||
1482 | return ret; | ||
1483 | list_add(&target->list, &ipt_target); | ||
1484 | up(&ipt_mutex); | ||
1485 | return ret; | ||
1486 | } | ||
1487 | |||
1488 | void | ||
1489 | ipt_unregister_target(struct ipt_target *target) | ||
1490 | { | ||
1491 | down(&ipt_mutex); | ||
1492 | LIST_DELETE(&ipt_target, target); | ||
1493 | up(&ipt_mutex); | ||
1494 | } | ||
1495 | |||
1496 | int | ||
1497 | ipt_register_match(struct ipt_match *match) | ||
1498 | { | ||
1499 | int ret; | ||
1500 | |||
1501 | ret = down_interruptible(&ipt_mutex); | ||
1502 | if (ret != 0) | ||
1503 | return ret; | ||
1504 | |||
1505 | list_add(&match->list, &ipt_match); | ||
1506 | up(&ipt_mutex); | ||
1507 | |||
1508 | return ret; | ||
1509 | } | ||
1510 | |||
1511 | void | ||
1512 | ipt_unregister_match(struct ipt_match *match) | ||
1513 | { | ||
1514 | down(&ipt_mutex); | ||
1515 | LIST_DELETE(&ipt_match, match); | ||
1516 | up(&ipt_mutex); | ||
1517 | } | ||
1518 | |||
1519 | int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl) | ||
1520 | { | ||
1521 | int ret; | ||
1522 | struct ipt_table_info *newinfo; | ||
1523 | static struct ipt_table_info bootstrap | ||
1524 | = { 0, 0, 0, { 0 }, { 0 }, { } }; | 1215 | = { 0, 0, 0, { 0 }, { 0 }, { } }; |
1525 | void *loc_cpu_entry; | 1216 | void *loc_cpu_entry; |
1526 | 1217 | ||
1527 | newinfo = alloc_table_info(repl->size); | 1218 | newinfo = xt_alloc_table_info(repl->size); |
1528 | if (!newinfo) | 1219 | if (!newinfo) |
1529 | return -ENOMEM; | 1220 | return -ENOMEM; |
1530 | 1221 | ||
@@ -1540,246 +1231,29 @@ int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl) | |||
1540 | repl->hook_entry, | 1231 | repl->hook_entry, |
1541 | repl->underflow); | 1232 | repl->underflow); |
1542 | if (ret != 0) { | 1233 | if (ret != 0) { |
1543 | free_table_info(newinfo); | 1234 | xt_free_table_info(newinfo); |
1544 | return ret; | 1235 | return ret; |
1545 | } | 1236 | } |
1546 | 1237 | ||
1547 | ret = down_interruptible(&ipt_mutex); | 1238 | if (xt_register_table(table, &bootstrap, newinfo) != 0) { |
1548 | if (ret != 0) { | 1239 | xt_free_table_info(newinfo); |
1549 | free_table_info(newinfo); | ||
1550 | return ret; | 1240 | return ret; |
1551 | } | 1241 | } |
1552 | 1242 | ||
1553 | /* Don't autoload: we'd eat our tail... */ | 1243 | return 0; |
1554 | if (list_named_find(&ipt_tables, table->name)) { | ||
1555 | ret = -EEXIST; | ||
1556 | goto free_unlock; | ||
1557 | } | ||
1558 | |||
1559 | /* Simplifies replace_table code. */ | ||
1560 | table->private = &bootstrap; | ||
1561 | if (!replace_table(table, 0, newinfo, &ret)) | ||
1562 | goto free_unlock; | ||
1563 | |||
1564 | duprintf("table->private->number = %u\n", | ||
1565 | table->private->number); | ||
1566 | |||
1567 | /* save number of initial entries */ | ||
1568 | table->private->initial_entries = table->private->number; | ||
1569 | |||
1570 | rwlock_init(&table->lock); | ||
1571 | list_prepend(&ipt_tables, table); | ||
1572 | |||
1573 | unlock: | ||
1574 | up(&ipt_mutex); | ||
1575 | return ret; | ||
1576 | |||
1577 | free_unlock: | ||
1578 | free_table_info(newinfo); | ||
1579 | goto unlock; | ||
1580 | } | 1244 | } |
1581 | 1245 | ||
1582 | void ipt_unregister_table(struct ipt_table *table) | 1246 | void ipt_unregister_table(struct ipt_table *table) |
1583 | { | 1247 | { |
1248 | struct xt_table_info *private; | ||
1584 | void *loc_cpu_entry; | 1249 | void *loc_cpu_entry; |
1585 | 1250 | ||
1586 | down(&ipt_mutex); | 1251 | private = xt_unregister_table(table); |
1587 | LIST_DELETE(&ipt_tables, table); | ||
1588 | up(&ipt_mutex); | ||
1589 | 1252 | ||
1590 | /* Decrease module usage counts and free resources */ | 1253 | /* Decrease module usage counts and free resources */ |
1591 | loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; | 1254 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
1592 | IPT_ENTRY_ITERATE(loc_cpu_entry, table->private->size, | 1255 | IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); |
1593 | cleanup_entry, NULL); | 1256 | xt_free_table_info(private); |
1594 | free_table_info(table->private); | ||
1595 | } | ||
1596 | |||
1597 | /* Returns 1 if the port is matched by the range, 0 otherwise */ | ||
1598 | static inline int | ||
1599 | port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert) | ||
1600 | { | ||
1601 | int ret; | ||
1602 | |||
1603 | ret = (port >= min && port <= max) ^ invert; | ||
1604 | return ret; | ||
1605 | } | ||
1606 | |||
1607 | static int | ||
1608 | tcp_find_option(u_int8_t option, | ||
1609 | const struct sk_buff *skb, | ||
1610 | unsigned int optlen, | ||
1611 | int invert, | ||
1612 | int *hotdrop) | ||
1613 | { | ||
1614 | /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ | ||
1615 | u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; | ||
1616 | unsigned int i; | ||
1617 | |||
1618 | duprintf("tcp_match: finding option\n"); | ||
1619 | |||
1620 | if (!optlen) | ||
1621 | return invert; | ||
1622 | |||
1623 | /* If we don't have the whole header, drop packet. */ | ||
1624 | op = skb_header_pointer(skb, | ||
1625 | skb->nh.iph->ihl*4 + sizeof(struct tcphdr), | ||
1626 | optlen, _opt); | ||
1627 | if (op == NULL) { | ||
1628 | *hotdrop = 1; | ||
1629 | return 0; | ||
1630 | } | ||
1631 | |||
1632 | for (i = 0; i < optlen; ) { | ||
1633 | if (op[i] == option) return !invert; | ||
1634 | if (op[i] < 2) i++; | ||
1635 | else i += op[i+1]?:1; | ||
1636 | } | ||
1637 | |||
1638 | return invert; | ||
1639 | } | ||
1640 | |||
1641 | static int | ||
1642 | tcp_match(const struct sk_buff *skb, | ||
1643 | const struct net_device *in, | ||
1644 | const struct net_device *out, | ||
1645 | const void *matchinfo, | ||
1646 | int offset, | ||
1647 | int *hotdrop) | ||
1648 | { | ||
1649 | struct tcphdr _tcph, *th; | ||
1650 | const struct ipt_tcp *tcpinfo = matchinfo; | ||
1651 | |||
1652 | if (offset) { | ||
1653 | /* To quote Alan: | ||
1654 | |||
1655 | Don't allow a fragment of TCP 8 bytes in. Nobody normal | ||
1656 | causes this. Its a cracker trying to break in by doing a | ||
1657 | flag overwrite to pass the direction checks. | ||
1658 | */ | ||
1659 | if (offset == 1) { | ||
1660 | duprintf("Dropping evil TCP offset=1 frag.\n"); | ||
1661 | *hotdrop = 1; | ||
1662 | } | ||
1663 | /* Must not be a fragment. */ | ||
1664 | return 0; | ||
1665 | } | ||
1666 | |||
1667 | #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) | ||
1668 | |||
1669 | th = skb_header_pointer(skb, skb->nh.iph->ihl*4, | ||
1670 | sizeof(_tcph), &_tcph); | ||
1671 | if (th == NULL) { | ||
1672 | /* We've been asked to examine this packet, and we | ||
1673 | can't. Hence, no choice but to drop. */ | ||
1674 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); | ||
1675 | *hotdrop = 1; | ||
1676 | return 0; | ||
1677 | } | ||
1678 | |||
1679 | if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], | ||
1680 | ntohs(th->source), | ||
1681 | !!(tcpinfo->invflags & IPT_TCP_INV_SRCPT))) | ||
1682 | return 0; | ||
1683 | if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], | ||
1684 | ntohs(th->dest), | ||
1685 | !!(tcpinfo->invflags & IPT_TCP_INV_DSTPT))) | ||
1686 | return 0; | ||
1687 | if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) | ||
1688 | == tcpinfo->flg_cmp, | ||
1689 | IPT_TCP_INV_FLAGS)) | ||
1690 | return 0; | ||
1691 | if (tcpinfo->option) { | ||
1692 | if (th->doff * 4 < sizeof(_tcph)) { | ||
1693 | *hotdrop = 1; | ||
1694 | return 0; | ||
1695 | } | ||
1696 | if (!tcp_find_option(tcpinfo->option, skb, | ||
1697 | th->doff*4 - sizeof(_tcph), | ||
1698 | tcpinfo->invflags & IPT_TCP_INV_OPTION, | ||
1699 | hotdrop)) | ||
1700 | return 0; | ||
1701 | } | ||
1702 | return 1; | ||
1703 | } | ||
1704 | |||
1705 | /* Called when user tries to insert an entry of this type. */ | ||
1706 | static int | ||
1707 | tcp_checkentry(const char *tablename, | ||
1708 | const struct ipt_ip *ip, | ||
1709 | void *matchinfo, | ||
1710 | unsigned int matchsize, | ||
1711 | unsigned int hook_mask) | ||
1712 | { | ||
1713 | const struct ipt_tcp *tcpinfo = matchinfo; | ||
1714 | |||
1715 | /* Must specify proto == TCP, and no unknown invflags */ | ||
1716 | return ip->proto == IPPROTO_TCP | ||
1717 | && !(ip->invflags & IPT_INV_PROTO) | ||
1718 | && matchsize == IPT_ALIGN(sizeof(struct ipt_tcp)) | ||
1719 | && !(tcpinfo->invflags & ~IPT_TCP_INV_MASK); | ||
1720 | } | ||
1721 | |||
1722 | static int | ||
1723 | udp_match(const struct sk_buff *skb, | ||
1724 | const struct net_device *in, | ||
1725 | const struct net_device *out, | ||
1726 | const void *matchinfo, | ||
1727 | int offset, | ||
1728 | int *hotdrop) | ||
1729 | { | ||
1730 | struct udphdr _udph, *uh; | ||
1731 | const struct ipt_udp *udpinfo = matchinfo; | ||
1732 | |||
1733 | /* Must not be a fragment. */ | ||
1734 | if (offset) | ||
1735 | return 0; | ||
1736 | |||
1737 | uh = skb_header_pointer(skb, skb->nh.iph->ihl*4, | ||
1738 | sizeof(_udph), &_udph); | ||
1739 | if (uh == NULL) { | ||
1740 | /* We've been asked to examine this packet, and we | ||
1741 | can't. Hence, no choice but to drop. */ | ||
1742 | duprintf("Dropping evil UDP tinygram.\n"); | ||
1743 | *hotdrop = 1; | ||
1744 | return 0; | ||
1745 | } | ||
1746 | |||
1747 | return port_match(udpinfo->spts[0], udpinfo->spts[1], | ||
1748 | ntohs(uh->source), | ||
1749 | !!(udpinfo->invflags & IPT_UDP_INV_SRCPT)) | ||
1750 | && port_match(udpinfo->dpts[0], udpinfo->dpts[1], | ||
1751 | ntohs(uh->dest), | ||
1752 | !!(udpinfo->invflags & IPT_UDP_INV_DSTPT)); | ||
1753 | } | ||
1754 | |||
1755 | /* Called when user tries to insert an entry of this type. */ | ||
1756 | static int | ||
1757 | udp_checkentry(const char *tablename, | ||
1758 | const struct ipt_ip *ip, | ||
1759 | void *matchinfo, | ||
1760 | unsigned int matchinfosize, | ||
1761 | unsigned int hook_mask) | ||
1762 | { | ||
1763 | const struct ipt_udp *udpinfo = matchinfo; | ||
1764 | |||
1765 | /* Must specify proto == UDP, and no unknown invflags */ | ||
1766 | if (ip->proto != IPPROTO_UDP || (ip->invflags & IPT_INV_PROTO)) { | ||
1767 | duprintf("ipt_udp: Protocol %u != %u\n", ip->proto, | ||
1768 | IPPROTO_UDP); | ||
1769 | return 0; | ||
1770 | } | ||
1771 | if (matchinfosize != IPT_ALIGN(sizeof(struct ipt_udp))) { | ||
1772 | duprintf("ipt_udp: matchsize %u != %u\n", | ||
1773 | matchinfosize, IPT_ALIGN(sizeof(struct ipt_udp))); | ||
1774 | return 0; | ||
1775 | } | ||
1776 | if (udpinfo->invflags & ~IPT_UDP_INV_MASK) { | ||
1777 | duprintf("ipt_udp: unknown flags %X\n", | ||
1778 | udpinfo->invflags); | ||
1779 | return 0; | ||
1780 | } | ||
1781 | |||
1782 | return 1; | ||
1783 | } | 1257 | } |
1784 | 1258 | ||
1785 | /* Returns 1 if the type and code is matched by the range, 0 otherwise */ | 1259 | /* Returns 1 if the type and code is matched by the range, 0 otherwise */ |
@@ -1798,6 +1272,7 @@ icmp_match(const struct sk_buff *skb, | |||
1798 | const struct net_device *out, | 1272 | const struct net_device *out, |
1799 | const void *matchinfo, | 1273 | const void *matchinfo, |
1800 | int offset, | 1274 | int offset, |
1275 | unsigned int protoff, | ||
1801 | int *hotdrop) | 1276 | int *hotdrop) |
1802 | { | 1277 | { |
1803 | struct icmphdr _icmph, *ic; | 1278 | struct icmphdr _icmph, *ic; |
@@ -1807,8 +1282,7 @@ icmp_match(const struct sk_buff *skb, | |||
1807 | if (offset) | 1282 | if (offset) |
1808 | return 0; | 1283 | return 0; |
1809 | 1284 | ||
1810 | ic = skb_header_pointer(skb, skb->nh.iph->ihl*4, | 1285 | ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph); |
1811 | sizeof(_icmph), &_icmph); | ||
1812 | if (ic == NULL) { | 1286 | if (ic == NULL) { |
1813 | /* We've been asked to examine this packet, and we | 1287 | /* We've been asked to examine this packet, and we |
1814 | * can't. Hence, no choice but to drop. | 1288 | * can't. Hence, no choice but to drop. |
@@ -1828,11 +1302,12 @@ icmp_match(const struct sk_buff *skb, | |||
1828 | /* Called when user tries to insert an entry of this type. */ | 1302 | /* Called when user tries to insert an entry of this type. */ |
1829 | static int | 1303 | static int |
1830 | icmp_checkentry(const char *tablename, | 1304 | icmp_checkentry(const char *tablename, |
1831 | const struct ipt_ip *ip, | 1305 | const void *info, |
1832 | void *matchinfo, | 1306 | void *matchinfo, |
1833 | unsigned int matchsize, | 1307 | unsigned int matchsize, |
1834 | unsigned int hook_mask) | 1308 | unsigned int hook_mask) |
1835 | { | 1309 | { |
1310 | const struct ipt_ip *ip = info; | ||
1836 | const struct ipt_icmp *icmpinfo = matchinfo; | 1311 | const struct ipt_icmp *icmpinfo = matchinfo; |
1837 | 1312 | ||
1838 | /* Must specify proto == ICMP, and no unknown invflags */ | 1313 | /* Must specify proto == ICMP, and no unknown invflags */ |
@@ -1862,123 +1337,22 @@ static struct nf_sockopt_ops ipt_sockopts = { | |||
1862 | .get = do_ipt_get_ctl, | 1337 | .get = do_ipt_get_ctl, |
1863 | }; | 1338 | }; |
1864 | 1339 | ||
1865 | static struct ipt_match tcp_matchstruct = { | ||
1866 | .name = "tcp", | ||
1867 | .match = &tcp_match, | ||
1868 | .checkentry = &tcp_checkentry, | ||
1869 | }; | ||
1870 | |||
1871 | static struct ipt_match udp_matchstruct = { | ||
1872 | .name = "udp", | ||
1873 | .match = &udp_match, | ||
1874 | .checkentry = &udp_checkentry, | ||
1875 | }; | ||
1876 | |||
1877 | static struct ipt_match icmp_matchstruct = { | 1340 | static struct ipt_match icmp_matchstruct = { |
1878 | .name = "icmp", | 1341 | .name = "icmp", |
1879 | .match = &icmp_match, | 1342 | .match = &icmp_match, |
1880 | .checkentry = &icmp_checkentry, | 1343 | .checkentry = &icmp_checkentry, |
1881 | }; | 1344 | }; |
1882 | 1345 | ||
1883 | #ifdef CONFIG_PROC_FS | ||
1884 | static inline int print_name(const char *i, | ||
1885 | off_t start_offset, char *buffer, int length, | ||
1886 | off_t *pos, unsigned int *count) | ||
1887 | { | ||
1888 | if ((*count)++ >= start_offset) { | ||
1889 | unsigned int namelen; | ||
1890 | |||
1891 | namelen = sprintf(buffer + *pos, "%s\n", | ||
1892 | i + sizeof(struct list_head)); | ||
1893 | if (*pos + namelen > length) { | ||
1894 | /* Stop iterating */ | ||
1895 | return 1; | ||
1896 | } | ||
1897 | *pos += namelen; | ||
1898 | } | ||
1899 | return 0; | ||
1900 | } | ||
1901 | |||
1902 | static inline int print_target(const struct ipt_target *t, | ||
1903 | off_t start_offset, char *buffer, int length, | ||
1904 | off_t *pos, unsigned int *count) | ||
1905 | { | ||
1906 | if (t == &ipt_standard_target || t == &ipt_error_target) | ||
1907 | return 0; | ||
1908 | return print_name((char *)t, start_offset, buffer, length, pos, count); | ||
1909 | } | ||
1910 | |||
1911 | static int ipt_get_tables(char *buffer, char **start, off_t offset, int length) | ||
1912 | { | ||
1913 | off_t pos = 0; | ||
1914 | unsigned int count = 0; | ||
1915 | |||
1916 | if (down_interruptible(&ipt_mutex) != 0) | ||
1917 | return 0; | ||
1918 | |||
1919 | LIST_FIND(&ipt_tables, print_name, void *, | ||
1920 | offset, buffer, length, &pos, &count); | ||
1921 | |||
1922 | up(&ipt_mutex); | ||
1923 | |||
1924 | /* `start' hack - see fs/proc/generic.c line ~105 */ | ||
1925 | *start=(char *)((unsigned long)count-offset); | ||
1926 | return pos; | ||
1927 | } | ||
1928 | |||
1929 | static int ipt_get_targets(char *buffer, char **start, off_t offset, int length) | ||
1930 | { | ||
1931 | off_t pos = 0; | ||
1932 | unsigned int count = 0; | ||
1933 | |||
1934 | if (down_interruptible(&ipt_mutex) != 0) | ||
1935 | return 0; | ||
1936 | |||
1937 | LIST_FIND(&ipt_target, print_target, struct ipt_target *, | ||
1938 | offset, buffer, length, &pos, &count); | ||
1939 | |||
1940 | up(&ipt_mutex); | ||
1941 | |||
1942 | *start = (char *)((unsigned long)count - offset); | ||
1943 | return pos; | ||
1944 | } | ||
1945 | |||
1946 | static int ipt_get_matches(char *buffer, char **start, off_t offset, int length) | ||
1947 | { | ||
1948 | off_t pos = 0; | ||
1949 | unsigned int count = 0; | ||
1950 | |||
1951 | if (down_interruptible(&ipt_mutex) != 0) | ||
1952 | return 0; | ||
1953 | |||
1954 | LIST_FIND(&ipt_match, print_name, void *, | ||
1955 | offset, buffer, length, &pos, &count); | ||
1956 | |||
1957 | up(&ipt_mutex); | ||
1958 | |||
1959 | *start = (char *)((unsigned long)count - offset); | ||
1960 | return pos; | ||
1961 | } | ||
1962 | |||
1963 | static const struct { char *name; get_info_t *get_info; } ipt_proc_entry[] = | ||
1964 | { { "ip_tables_names", ipt_get_tables }, | ||
1965 | { "ip_tables_targets", ipt_get_targets }, | ||
1966 | { "ip_tables_matches", ipt_get_matches }, | ||
1967 | { NULL, NULL} }; | ||
1968 | #endif /*CONFIG_PROC_FS*/ | ||
1969 | |||
1970 | static int __init init(void) | 1346 | static int __init init(void) |
1971 | { | 1347 | { |
1972 | int ret; | 1348 | int ret; |
1973 | 1349 | ||
1350 | xt_proto_init(AF_INET); | ||
1351 | |||
1974 | /* Noone else will be downing sem now, so we won't sleep */ | 1352 | /* Noone else will be downing sem now, so we won't sleep */ |
1975 | down(&ipt_mutex); | 1353 | xt_register_target(AF_INET, &ipt_standard_target); |
1976 | list_append(&ipt_target, &ipt_standard_target); | 1354 | xt_register_target(AF_INET, &ipt_error_target); |
1977 | list_append(&ipt_target, &ipt_error_target); | 1355 | xt_register_match(AF_INET, &icmp_matchstruct); |
1978 | list_append(&ipt_match, &tcp_matchstruct); | ||
1979 | list_append(&ipt_match, &udp_matchstruct); | ||
1980 | list_append(&ipt_match, &icmp_matchstruct); | ||
1981 | up(&ipt_mutex); | ||
1982 | 1356 | ||
1983 | /* Register setsockopt */ | 1357 | /* Register setsockopt */ |
1984 | ret = nf_register_sockopt(&ipt_sockopts); | 1358 | ret = nf_register_sockopt(&ipt_sockopts); |
@@ -1987,49 +1361,23 @@ static int __init init(void) | |||
1987 | return ret; | 1361 | return ret; |
1988 | } | 1362 | } |
1989 | 1363 | ||
1990 | #ifdef CONFIG_PROC_FS | 1364 | printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n"); |
1991 | { | ||
1992 | struct proc_dir_entry *proc; | ||
1993 | int i; | ||
1994 | |||
1995 | for (i = 0; ipt_proc_entry[i].name; i++) { | ||
1996 | proc = proc_net_create(ipt_proc_entry[i].name, 0, | ||
1997 | ipt_proc_entry[i].get_info); | ||
1998 | if (!proc) { | ||
1999 | while (--i >= 0) | ||
2000 | proc_net_remove(ipt_proc_entry[i].name); | ||
2001 | nf_unregister_sockopt(&ipt_sockopts); | ||
2002 | return -ENOMEM; | ||
2003 | } | ||
2004 | proc->owner = THIS_MODULE; | ||
2005 | } | ||
2006 | } | ||
2007 | #endif | ||
2008 | |||
2009 | printk("ip_tables: (C) 2000-2002 Netfilter core team\n"); | ||
2010 | return 0; | 1365 | return 0; |
2011 | } | 1366 | } |
2012 | 1367 | ||
2013 | static void __exit fini(void) | 1368 | static void __exit fini(void) |
2014 | { | 1369 | { |
2015 | nf_unregister_sockopt(&ipt_sockopts); | 1370 | nf_unregister_sockopt(&ipt_sockopts); |
2016 | #ifdef CONFIG_PROC_FS | 1371 | |
2017 | { | 1372 | xt_unregister_match(AF_INET, &icmp_matchstruct); |
2018 | int i; | 1373 | xt_unregister_target(AF_INET, &ipt_error_target); |
2019 | for (i = 0; ipt_proc_entry[i].name; i++) | 1374 | xt_unregister_target(AF_INET, &ipt_standard_target); |
2020 | proc_net_remove(ipt_proc_entry[i].name); | 1375 | |
2021 | } | 1376 | xt_proto_fini(AF_INET); |
2022 | #endif | ||
2023 | } | 1377 | } |
2024 | 1378 | ||
2025 | EXPORT_SYMBOL(ipt_register_table); | 1379 | EXPORT_SYMBOL(ipt_register_table); |
2026 | EXPORT_SYMBOL(ipt_unregister_table); | 1380 | EXPORT_SYMBOL(ipt_unregister_table); |
2027 | EXPORT_SYMBOL(ipt_register_match); | ||
2028 | EXPORT_SYMBOL(ipt_unregister_match); | ||
2029 | EXPORT_SYMBOL(ipt_do_table); | 1381 | EXPORT_SYMBOL(ipt_do_table); |
2030 | EXPORT_SYMBOL(ipt_register_target); | ||
2031 | EXPORT_SYMBOL(ipt_unregister_target); | ||
2032 | EXPORT_SYMBOL(ipt_find_target); | ||
2033 | |||
2034 | module_init(init); | 1382 | module_init(init); |
2035 | module_exit(fini); | 1383 | module_exit(fini); |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 45c52d8f4d99..d9bc971f03af 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -379,12 +379,13 @@ target(struct sk_buff **pskb, | |||
379 | 379 | ||
380 | static int | 380 | static int |
381 | checkentry(const char *tablename, | 381 | checkentry(const char *tablename, |
382 | const struct ipt_entry *e, | 382 | const void *e_void, |
383 | void *targinfo, | 383 | void *targinfo, |
384 | unsigned int targinfosize, | 384 | unsigned int targinfosize, |
385 | unsigned int hook_mask) | 385 | unsigned int hook_mask) |
386 | { | 386 | { |
387 | struct ipt_clusterip_tgt_info *cipinfo = targinfo; | 387 | struct ipt_clusterip_tgt_info *cipinfo = targinfo; |
388 | const struct ipt_entry *e = e_void; | ||
388 | 389 | ||
389 | struct clusterip_config *config; | 390 | struct clusterip_config *config; |
390 | 391 | ||
diff --git a/net/ipv4/netfilter/ipt_DSCP.c b/net/ipv4/netfilter/ipt_DSCP.c index 6e319570a28c..898cdf79ce18 100644 --- a/net/ipv4/netfilter/ipt_DSCP.c +++ b/net/ipv4/netfilter/ipt_DSCP.c | |||
@@ -57,7 +57,7 @@ target(struct sk_buff **pskb, | |||
57 | 57 | ||
58 | static int | 58 | static int |
59 | checkentry(const char *tablename, | 59 | checkentry(const char *tablename, |
60 | const struct ipt_entry *e, | 60 | const void *e_void, |
61 | void *targinfo, | 61 | void *targinfo, |
62 | unsigned int targinfosize, | 62 | unsigned int targinfosize, |
63 | unsigned int hook_mask) | 63 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c index a1319693f648..706445426a6d 100644 --- a/net/ipv4/netfilter/ipt_ECN.c +++ b/net/ipv4/netfilter/ipt_ECN.c | |||
@@ -113,12 +113,13 @@ target(struct sk_buff **pskb, | |||
113 | 113 | ||
114 | static int | 114 | static int |
115 | checkentry(const char *tablename, | 115 | checkentry(const char *tablename, |
116 | const struct ipt_entry *e, | 116 | const void *e_void, |
117 | void *targinfo, | 117 | void *targinfo, |
118 | unsigned int targinfosize, | 118 | unsigned int targinfosize, |
119 | unsigned int hook_mask) | 119 | unsigned int hook_mask) |
120 | { | 120 | { |
121 | const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; | 121 | const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; |
122 | const struct ipt_entry *e = e_void; | ||
122 | 123 | ||
123 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) { | 124 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) { |
124 | printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n", | 125 | printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n", |
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 30be0f1dae37..6606ddb66a29 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c | |||
@@ -431,7 +431,7 @@ ipt_log_target(struct sk_buff **pskb, | |||
431 | } | 431 | } |
432 | 432 | ||
433 | static int ipt_log_checkentry(const char *tablename, | 433 | static int ipt_log_checkentry(const char *tablename, |
434 | const struct ipt_entry *e, | 434 | const void *e, |
435 | void *targinfo, | 435 | void *targinfo, |
436 | unsigned int targinfosize, | 436 | unsigned int targinfosize, |
437 | unsigned int hook_mask) | 437 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 27860510ca6d..12c56d3343ca 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c | |||
@@ -40,7 +40,7 @@ static DEFINE_RWLOCK(masq_lock); | |||
40 | /* FIXME: Multiple targets. --RR */ | 40 | /* FIXME: Multiple targets. --RR */ |
41 | static int | 41 | static int |
42 | masquerade_check(const char *tablename, | 42 | masquerade_check(const char *tablename, |
43 | const struct ipt_entry *e, | 43 | const void *e, |
44 | void *targinfo, | 44 | void *targinfo, |
45 | unsigned int targinfosize, | 45 | unsigned int targinfosize, |
46 | unsigned int hook_mask) | 46 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c index e6e7b6095363..b074467fe67b 100644 --- a/net/ipv4/netfilter/ipt_NETMAP.c +++ b/net/ipv4/netfilter/ipt_NETMAP.c | |||
@@ -31,7 +31,7 @@ MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target"); | |||
31 | 31 | ||
32 | static int | 32 | static int |
33 | check(const char *tablename, | 33 | check(const char *tablename, |
34 | const struct ipt_entry *e, | 34 | const void *e, |
35 | void *targinfo, | 35 | void *targinfo, |
36 | unsigned int targinfosize, | 36 | unsigned int targinfosize, |
37 | unsigned int hook_mask) | 37 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_NFQUEUE.c b/net/ipv4/netfilter/ipt_NFQUEUE.c deleted file mode 100644 index 3cedc9be8807..000000000000 --- a/net/ipv4/netfilter/ipt_NFQUEUE.c +++ /dev/null | |||
@@ -1,70 +0,0 @@ | |||
1 | /* iptables module for using new netfilter netlink queue | ||
2 | * | ||
3 | * (C) 2005 by Harald Welte <laforge@netfilter.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | |||
14 | #include <linux/netfilter.h> | ||
15 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
16 | #include <linux/netfilter_ipv4/ipt_NFQUEUE.h> | ||
17 | |||
18 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | ||
19 | MODULE_DESCRIPTION("iptables NFQUEUE target"); | ||
20 | MODULE_LICENSE("GPL"); | ||
21 | |||
22 | static unsigned int | ||
23 | target(struct sk_buff **pskb, | ||
24 | const struct net_device *in, | ||
25 | const struct net_device *out, | ||
26 | unsigned int hooknum, | ||
27 | const void *targinfo, | ||
28 | void *userinfo) | ||
29 | { | ||
30 | const struct ipt_NFQ_info *tinfo = targinfo; | ||
31 | |||
32 | return NF_QUEUE_NR(tinfo->queuenum); | ||
33 | } | ||
34 | |||
35 | static int | ||
36 | checkentry(const char *tablename, | ||
37 | const struct ipt_entry *e, | ||
38 | void *targinfo, | ||
39 | unsigned int targinfosize, | ||
40 | unsigned int hook_mask) | ||
41 | { | ||
42 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_NFQ_info))) { | ||
43 | printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n", | ||
44 | targinfosize, | ||
45 | IPT_ALIGN(sizeof(struct ipt_NFQ_info))); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | return 1; | ||
50 | } | ||
51 | |||
52 | static struct ipt_target ipt_NFQ_reg = { | ||
53 | .name = "NFQUEUE", | ||
54 | .target = target, | ||
55 | .checkentry = checkentry, | ||
56 | .me = THIS_MODULE, | ||
57 | }; | ||
58 | |||
59 | static int __init init(void) | ||
60 | { | ||
61 | return ipt_register_target(&ipt_NFQ_reg); | ||
62 | } | ||
63 | |||
64 | static void __exit fini(void) | ||
65 | { | ||
66 | ipt_unregister_target(&ipt_NFQ_reg); | ||
67 | } | ||
68 | |||
69 | module_init(init); | ||
70 | module_exit(fini); | ||
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c index 5245bfd33d52..140be51f2f01 100644 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/net/ipv4/netfilter/ipt_REDIRECT.c | |||
@@ -33,7 +33,7 @@ MODULE_DESCRIPTION("iptables REDIRECT target module"); | |||
33 | /* FIXME: Take multiple ranges --RR */ | 33 | /* FIXME: Take multiple ranges --RR */ |
34 | static int | 34 | static int |
35 | redirect_check(const char *tablename, | 35 | redirect_check(const char *tablename, |
36 | const struct ipt_entry *e, | 36 | const void *e, |
37 | void *targinfo, | 37 | void *targinfo, |
38 | unsigned int targinfosize, | 38 | unsigned int targinfosize, |
39 | unsigned int hook_mask) | 39 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 6693526ae128..3eb47aae78c5 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
@@ -282,12 +282,13 @@ static unsigned int reject(struct sk_buff **pskb, | |||
282 | } | 282 | } |
283 | 283 | ||
284 | static int check(const char *tablename, | 284 | static int check(const char *tablename, |
285 | const struct ipt_entry *e, | 285 | const void *e_void, |
286 | void *targinfo, | 286 | void *targinfo, |
287 | unsigned int targinfosize, | 287 | unsigned int targinfosize, |
288 | unsigned int hook_mask) | 288 | unsigned int hook_mask) |
289 | { | 289 | { |
290 | const struct ipt_reject_info *rejinfo = targinfo; | 290 | const struct ipt_reject_info *rejinfo = targinfo; |
291 | const struct ipt_entry *e = e_void; | ||
291 | 292 | ||
292 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) { | 293 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) { |
293 | DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize); | 294 | DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize); |
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c index 7a0536d864ac..a22de59bba0e 100644 --- a/net/ipv4/netfilter/ipt_SAME.c +++ b/net/ipv4/netfilter/ipt_SAME.c | |||
@@ -49,7 +49,7 @@ MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip"); | |||
49 | 49 | ||
50 | static int | 50 | static int |
51 | same_check(const char *tablename, | 51 | same_check(const char *tablename, |
52 | const struct ipt_entry *e, | 52 | const void *e, |
53 | void *targinfo, | 53 | void *targinfo, |
54 | unsigned int targinfosize, | 54 | unsigned int targinfosize, |
55 | unsigned int hook_mask) | 55 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c index 8db70d6908c3..c122841e182c 100644 --- a/net/ipv4/netfilter/ipt_TCPMSS.c +++ b/net/ipv4/netfilter/ipt_TCPMSS.c | |||
@@ -210,12 +210,13 @@ static inline int find_syn_match(const struct ipt_entry_match *m) | |||
210 | /* Must specify -p tcp --syn/--tcp-flags SYN */ | 210 | /* Must specify -p tcp --syn/--tcp-flags SYN */ |
211 | static int | 211 | static int |
212 | ipt_tcpmss_checkentry(const char *tablename, | 212 | ipt_tcpmss_checkentry(const char *tablename, |
213 | const struct ipt_entry *e, | 213 | const void *e_void, |
214 | void *targinfo, | 214 | void *targinfo, |
215 | unsigned int targinfosize, | 215 | unsigned int targinfosize, |
216 | unsigned int hook_mask) | 216 | unsigned int hook_mask) |
217 | { | 217 | { |
218 | const struct ipt_tcpmss_info *tcpmssinfo = targinfo; | 218 | const struct ipt_tcpmss_info *tcpmssinfo = targinfo; |
219 | const struct ipt_entry *e = e_void; | ||
219 | 220 | ||
220 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) { | 221 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) { |
221 | DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n", | 222 | DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n", |
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c index deadb36d4428..3a44a56db239 100644 --- a/net/ipv4/netfilter/ipt_TOS.c +++ b/net/ipv4/netfilter/ipt_TOS.c | |||
@@ -52,7 +52,7 @@ target(struct sk_buff **pskb, | |||
52 | 52 | ||
53 | static int | 53 | static int |
54 | checkentry(const char *tablename, | 54 | checkentry(const char *tablename, |
55 | const struct ipt_entry *e, | 55 | const void *e_void, |
56 | void *targinfo, | 56 | void *targinfo, |
57 | unsigned int targinfosize, | 57 | unsigned int targinfosize, |
58 | unsigned int hook_mask) | 58 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c index b9ae6a9382f3..b769eb231970 100644 --- a/net/ipv4/netfilter/ipt_TTL.c +++ b/net/ipv4/netfilter/ipt_TTL.c | |||
@@ -66,7 +66,7 @@ ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in, | |||
66 | } | 66 | } |
67 | 67 | ||
68 | static int ipt_ttl_checkentry(const char *tablename, | 68 | static int ipt_ttl_checkentry(const char *tablename, |
69 | const struct ipt_entry *e, | 69 | const void *e, |
70 | void *targinfo, | 70 | void *targinfo, |
71 | unsigned int targinfosize, | 71 | unsigned int targinfosize, |
72 | unsigned int hook_mask) | 72 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 38641cd06123..641dbc477650 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
@@ -330,7 +330,7 @@ static void ipt_logfn(unsigned int pf, | |||
330 | } | 330 | } |
331 | 331 | ||
332 | static int ipt_ulog_checkentry(const char *tablename, | 332 | static int ipt_ulog_checkentry(const char *tablename, |
333 | const struct ipt_entry *e, | 333 | const void *e, |
334 | void *targinfo, | 334 | void *targinfo, |
335 | unsigned int targinfosize, | 335 | unsigned int targinfosize, |
336 | unsigned int hookmask) | 336 | unsigned int hookmask) |
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c index e19c2a52d00c..d6b83a976518 100644 --- a/net/ipv4/netfilter/ipt_addrtype.c +++ b/net/ipv4/netfilter/ipt_addrtype.c | |||
@@ -29,7 +29,7 @@ static inline int match_type(u_int32_t addr, u_int16_t mask) | |||
29 | 29 | ||
30 | static int match(const struct sk_buff *skb, const struct net_device *in, | 30 | static int match(const struct sk_buff *skb, const struct net_device *in, |
31 | const struct net_device *out, const void *matchinfo, | 31 | const struct net_device *out, const void *matchinfo, |
32 | int offset, int *hotdrop) | 32 | int offset, unsigned int protoff, int *hotdrop) |
33 | { | 33 | { |
34 | const struct ipt_addrtype_info *info = matchinfo; | 34 | const struct ipt_addrtype_info *info = matchinfo; |
35 | const struct iphdr *iph = skb->nh.iph; | 35 | const struct iphdr *iph = skb->nh.iph; |
@@ -43,7 +43,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, | |||
43 | return ret; | 43 | return ret; |
44 | } | 44 | } |
45 | 45 | ||
46 | static int checkentry(const char *tablename, const struct ipt_ip *ip, | 46 | static int checkentry(const char *tablename, const void *ip, |
47 | void *matchinfo, unsigned int matchsize, | 47 | void *matchinfo, unsigned int matchsize, |
48 | unsigned int hook_mask) | 48 | unsigned int hook_mask) |
49 | { | 49 | { |
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c index a0fea847cb72..144adfec13cc 100644 --- a/net/ipv4/netfilter/ipt_ah.c +++ b/net/ipv4/netfilter/ipt_ah.c | |||
@@ -41,6 +41,7 @@ match(const struct sk_buff *skb, | |||
41 | const struct net_device *out, | 41 | const struct net_device *out, |
42 | const void *matchinfo, | 42 | const void *matchinfo, |
43 | int offset, | 43 | int offset, |
44 | unsigned int protoff, | ||
44 | int *hotdrop) | 45 | int *hotdrop) |
45 | { | 46 | { |
46 | struct ip_auth_hdr _ahdr, *ah; | 47 | struct ip_auth_hdr _ahdr, *ah; |
@@ -50,7 +51,7 @@ match(const struct sk_buff *skb, | |||
50 | if (offset) | 51 | if (offset) |
51 | return 0; | 52 | return 0; |
52 | 53 | ||
53 | ah = skb_header_pointer(skb, skb->nh.iph->ihl * 4, | 54 | ah = skb_header_pointer(skb, protoff, |
54 | sizeof(_ahdr), &_ahdr); | 55 | sizeof(_ahdr), &_ahdr); |
55 | if (ah == NULL) { | 56 | if (ah == NULL) { |
56 | /* We've been asked to examine this packet, and we | 57 | /* We've been asked to examine this packet, and we |
@@ -69,12 +70,13 @@ match(const struct sk_buff *skb, | |||
69 | /* Called when user tries to insert an entry of this type. */ | 70 | /* Called when user tries to insert an entry of this type. */ |
70 | static int | 71 | static int |
71 | checkentry(const char *tablename, | 72 | checkentry(const char *tablename, |
72 | const struct ipt_ip *ip, | 73 | const void *ip_void, |
73 | void *matchinfo, | 74 | void *matchinfo, |
74 | unsigned int matchinfosize, | 75 | unsigned int matchinfosize, |
75 | unsigned int hook_mask) | 76 | unsigned int hook_mask) |
76 | { | 77 | { |
77 | const struct ipt_ah *ahinfo = matchinfo; | 78 | const struct ipt_ah *ahinfo = matchinfo; |
79 | const struct ipt_ip *ip = ip_void; | ||
78 | 80 | ||
79 | /* Must specify proto == AH, and no unknown invflags */ | 81 | /* Must specify proto == AH, and no unknown invflags */ |
80 | if (ip->proto != IPPROTO_AH || (ip->invflags & IPT_INV_PROTO)) { | 82 | if (ip->proto != IPPROTO_AH || (ip->invflags & IPT_INV_PROTO)) { |
diff --git a/net/ipv4/netfilter/ipt_dscp.c b/net/ipv4/netfilter/ipt_dscp.c index 5df52a64a5d4..92063b4f8602 100644 --- a/net/ipv4/netfilter/ipt_dscp.c +++ b/net/ipv4/netfilter/ipt_dscp.c | |||
@@ -21,7 +21,7 @@ MODULE_LICENSE("GPL"); | |||
21 | 21 | ||
22 | static int match(const struct sk_buff *skb, const struct net_device *in, | 22 | static int match(const struct sk_buff *skb, const struct net_device *in, |
23 | const struct net_device *out, const void *matchinfo, | 23 | const struct net_device *out, const void *matchinfo, |
24 | int offset, int *hotdrop) | 24 | int offset, unsigned int protoff, int *hotdrop) |
25 | { | 25 | { |
26 | const struct ipt_dscp_info *info = matchinfo; | 26 | const struct ipt_dscp_info *info = matchinfo; |
27 | const struct iphdr *iph = skb->nh.iph; | 27 | const struct iphdr *iph = skb->nh.iph; |
@@ -31,7 +31,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, | |||
31 | return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert; | 31 | return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert; |
32 | } | 32 | } |
33 | 33 | ||
34 | static int checkentry(const char *tablename, const struct ipt_ip *ip, | 34 | static int checkentry(const char *tablename, const void *ip, |
35 | void *matchinfo, unsigned int matchsize, | 35 | void *matchinfo, unsigned int matchsize, |
36 | unsigned int hook_mask) | 36 | unsigned int hook_mask) |
37 | { | 37 | { |
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c index b6f7181e89cc..e68b0c7981f0 100644 --- a/net/ipv4/netfilter/ipt_ecn.c +++ b/net/ipv4/netfilter/ipt_ecn.c | |||
@@ -67,7 +67,7 @@ static inline int match_tcp(const struct sk_buff *skb, | |||
67 | 67 | ||
68 | static int match(const struct sk_buff *skb, const struct net_device *in, | 68 | static int match(const struct sk_buff *skb, const struct net_device *in, |
69 | const struct net_device *out, const void *matchinfo, | 69 | const struct net_device *out, const void *matchinfo, |
70 | int offset, int *hotdrop) | 70 | int offset, unsigned int protoff, int *hotdrop) |
71 | { | 71 | { |
72 | const struct ipt_ecn_info *info = matchinfo; | 72 | const struct ipt_ecn_info *info = matchinfo; |
73 | 73 | ||
@@ -85,11 +85,12 @@ static int match(const struct sk_buff *skb, const struct net_device *in, | |||
85 | return 1; | 85 | return 1; |
86 | } | 86 | } |
87 | 87 | ||
88 | static int checkentry(const char *tablename, const struct ipt_ip *ip, | 88 | static int checkentry(const char *tablename, const void *ip_void, |
89 | void *matchinfo, unsigned int matchsize, | 89 | void *matchinfo, unsigned int matchsize, |
90 | unsigned int hook_mask) | 90 | unsigned int hook_mask) |
91 | { | 91 | { |
92 | const struct ipt_ecn_info *info = matchinfo; | 92 | const struct ipt_ecn_info *info = matchinfo; |
93 | const struct ipt_ip *ip = ip_void; | ||
93 | 94 | ||
94 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_ecn_info))) | 95 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_ecn_info))) |
95 | return 0; | 96 | return 0; |
diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/ipv4/netfilter/ipt_esp.c index e1d0dd31e117..9de191a8162d 100644 --- a/net/ipv4/netfilter/ipt_esp.c +++ b/net/ipv4/netfilter/ipt_esp.c | |||
@@ -42,6 +42,7 @@ match(const struct sk_buff *skb, | |||
42 | const struct net_device *out, | 42 | const struct net_device *out, |
43 | const void *matchinfo, | 43 | const void *matchinfo, |
44 | int offset, | 44 | int offset, |
45 | unsigned int protoff, | ||
45 | int *hotdrop) | 46 | int *hotdrop) |
46 | { | 47 | { |
47 | struct ip_esp_hdr _esp, *eh; | 48 | struct ip_esp_hdr _esp, *eh; |
@@ -51,7 +52,7 @@ match(const struct sk_buff *skb, | |||
51 | if (offset) | 52 | if (offset) |
52 | return 0; | 53 | return 0; |
53 | 54 | ||
54 | eh = skb_header_pointer(skb, skb->nh.iph->ihl * 4, | 55 | eh = skb_header_pointer(skb, protoff, |
55 | sizeof(_esp), &_esp); | 56 | sizeof(_esp), &_esp); |
56 | if (eh == NULL) { | 57 | if (eh == NULL) { |
57 | /* We've been asked to examine this packet, and we | 58 | /* We've been asked to examine this packet, and we |
@@ -70,12 +71,13 @@ match(const struct sk_buff *skb, | |||
70 | /* Called when user tries to insert an entry of this type. */ | 71 | /* Called when user tries to insert an entry of this type. */ |
71 | static int | 72 | static int |
72 | checkentry(const char *tablename, | 73 | checkentry(const char *tablename, |
73 | const struct ipt_ip *ip, | 74 | const void *ip_void, |
74 | void *matchinfo, | 75 | void *matchinfo, |
75 | unsigned int matchinfosize, | 76 | unsigned int matchinfosize, |
76 | unsigned int hook_mask) | 77 | unsigned int hook_mask) |
77 | { | 78 | { |
78 | const struct ipt_esp *espinfo = matchinfo; | 79 | const struct ipt_esp *espinfo = matchinfo; |
80 | const struct ipt_ip *ip = ip_void; | ||
79 | 81 | ||
80 | /* Must specify proto == ESP, and no unknown invflags */ | 82 | /* Must specify proto == ESP, and no unknown invflags */ |
81 | if (ip->proto != IPPROTO_ESP || (ip->invflags & IPT_INV_PROTO)) { | 83 | if (ip->proto != IPPROTO_ESP || (ip->invflags & IPT_INV_PROTO)) { |
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c index 2dd1cccbdab9..4fe48c1bd5f3 100644 --- a/net/ipv4/netfilter/ipt_hashlimit.c +++ b/net/ipv4/netfilter/ipt_hashlimit.c | |||
@@ -429,6 +429,7 @@ hashlimit_match(const struct sk_buff *skb, | |||
429 | const struct net_device *out, | 429 | const struct net_device *out, |
430 | const void *matchinfo, | 430 | const void *matchinfo, |
431 | int offset, | 431 | int offset, |
432 | unsigned int protoff, | ||
432 | int *hotdrop) | 433 | int *hotdrop) |
433 | { | 434 | { |
434 | struct ipt_hashlimit_info *r = | 435 | struct ipt_hashlimit_info *r = |
@@ -504,7 +505,7 @@ hashlimit_match(const struct sk_buff *skb, | |||
504 | 505 | ||
505 | static int | 506 | static int |
506 | hashlimit_checkentry(const char *tablename, | 507 | hashlimit_checkentry(const char *tablename, |
507 | const struct ipt_ip *ip, | 508 | const void *inf, |
508 | void *matchinfo, | 509 | void *matchinfo, |
509 | unsigned int matchsize, | 510 | unsigned int matchsize, |
510 | unsigned int hook_mask) | 511 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c index b835b7b2e560..13fb16fb7892 100644 --- a/net/ipv4/netfilter/ipt_iprange.c +++ b/net/ipv4/netfilter/ipt_iprange.c | |||
@@ -28,7 +28,7 @@ match(const struct sk_buff *skb, | |||
28 | const struct net_device *in, | 28 | const struct net_device *in, |
29 | const struct net_device *out, | 29 | const struct net_device *out, |
30 | const void *matchinfo, | 30 | const void *matchinfo, |
31 | int offset, int *hotdrop) | 31 | int offset, unsigned int protoff, int *hotdrop) |
32 | { | 32 | { |
33 | const struct ipt_iprange_info *info = matchinfo; | 33 | const struct ipt_iprange_info *info = matchinfo; |
34 | const struct iphdr *iph = skb->nh.iph; | 34 | const struct iphdr *iph = skb->nh.iph; |
@@ -63,7 +63,7 @@ match(const struct sk_buff *skb, | |||
63 | } | 63 | } |
64 | 64 | ||
65 | static int check(const char *tablename, | 65 | static int check(const char *tablename, |
66 | const struct ipt_ip *ip, | 66 | const void *inf, |
67 | void *matchinfo, | 67 | void *matchinfo, |
68 | unsigned int matchsize, | 68 | unsigned int matchsize, |
69 | unsigned int hook_mask) | 69 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_length.c b/net/ipv4/netfilter/ipt_length.c deleted file mode 100644 index 4eabcfbda9d1..000000000000 --- a/net/ipv4/netfilter/ipt_length.c +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | /* Kernel module to match packet length. */ | ||
2 | /* (C) 1999-2001 James Morris <jmorros@intercode.com.au> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/skbuff.h> | ||
11 | |||
12 | #include <linux/netfilter_ipv4/ipt_length.h> | ||
13 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
14 | |||
15 | MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); | ||
16 | MODULE_DESCRIPTION("IP tables packet length matching module"); | ||
17 | MODULE_LICENSE("GPL"); | ||
18 | |||
19 | static int | ||
20 | match(const struct sk_buff *skb, | ||
21 | const struct net_device *in, | ||
22 | const struct net_device *out, | ||
23 | const void *matchinfo, | ||
24 | int offset, | ||
25 | int *hotdrop) | ||
26 | { | ||
27 | const struct ipt_length_info *info = matchinfo; | ||
28 | u_int16_t pktlen = ntohs(skb->nh.iph->tot_len); | ||
29 | |||
30 | return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; | ||
31 | } | ||
32 | |||
33 | static int | ||
34 | checkentry(const char *tablename, | ||
35 | const struct ipt_ip *ip, | ||
36 | void *matchinfo, | ||
37 | unsigned int matchsize, | ||
38 | unsigned int hook_mask) | ||
39 | { | ||
40 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_length_info))) | ||
41 | return 0; | ||
42 | |||
43 | return 1; | ||
44 | } | ||
45 | |||
46 | static struct ipt_match length_match = { | ||
47 | .name = "length", | ||
48 | .match = &match, | ||
49 | .checkentry = &checkentry, | ||
50 | .me = THIS_MODULE, | ||
51 | }; | ||
52 | |||
53 | static int __init init(void) | ||
54 | { | ||
55 | return ipt_register_match(&length_match); | ||
56 | } | ||
57 | |||
58 | static void __exit fini(void) | ||
59 | { | ||
60 | ipt_unregister_match(&length_match); | ||
61 | } | ||
62 | |||
63 | module_init(init); | ||
64 | module_exit(fini); | ||
diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c index 99e8188162e2..2d52326553f1 100644 --- a/net/ipv4/netfilter/ipt_multiport.c +++ b/net/ipv4/netfilter/ipt_multiport.c | |||
@@ -97,6 +97,7 @@ match(const struct sk_buff *skb, | |||
97 | const struct net_device *out, | 97 | const struct net_device *out, |
98 | const void *matchinfo, | 98 | const void *matchinfo, |
99 | int offset, | 99 | int offset, |
100 | unsigned int protoff, | ||
100 | int *hotdrop) | 101 | int *hotdrop) |
101 | { | 102 | { |
102 | u16 _ports[2], *pptr; | 103 | u16 _ports[2], *pptr; |
@@ -105,7 +106,7 @@ match(const struct sk_buff *skb, | |||
105 | if (offset) | 106 | if (offset) |
106 | return 0; | 107 | return 0; |
107 | 108 | ||
108 | pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4, | 109 | pptr = skb_header_pointer(skb, protoff, |
109 | sizeof(_ports), _ports); | 110 | sizeof(_ports), _ports); |
110 | if (pptr == NULL) { | 111 | if (pptr == NULL) { |
111 | /* We've been asked to examine this packet, and we | 112 | /* We've been asked to examine this packet, and we |
@@ -128,6 +129,7 @@ match_v1(const struct sk_buff *skb, | |||
128 | const struct net_device *out, | 129 | const struct net_device *out, |
129 | const void *matchinfo, | 130 | const void *matchinfo, |
130 | int offset, | 131 | int offset, |
132 | unsigned int protoff, | ||
131 | int *hotdrop) | 133 | int *hotdrop) |
132 | { | 134 | { |
133 | u16 _ports[2], *pptr; | 135 | u16 _ports[2], *pptr; |
@@ -136,7 +138,7 @@ match_v1(const struct sk_buff *skb, | |||
136 | if (offset) | 138 | if (offset) |
137 | return 0; | 139 | return 0; |
138 | 140 | ||
139 | pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4, | 141 | pptr = skb_header_pointer(skb, protoff, |
140 | sizeof(_ports), _ports); | 142 | sizeof(_ports), _ports); |
141 | if (pptr == NULL) { | 143 | if (pptr == NULL) { |
142 | /* We've been asked to examine this packet, and we | 144 | /* We've been asked to examine this packet, and we |
@@ -154,7 +156,7 @@ match_v1(const struct sk_buff *skb, | |||
154 | /* Called when user tries to insert an entry of this type. */ | 156 | /* Called when user tries to insert an entry of this type. */ |
155 | static int | 157 | static int |
156 | checkentry(const char *tablename, | 158 | checkentry(const char *tablename, |
157 | const struct ipt_ip *ip, | 159 | const void *ip, |
158 | void *matchinfo, | 160 | void *matchinfo, |
159 | unsigned int matchsize, | 161 | unsigned int matchsize, |
160 | unsigned int hook_mask) | 162 | unsigned int hook_mask) |
@@ -164,7 +166,7 @@ checkentry(const char *tablename, | |||
164 | 166 | ||
165 | static int | 167 | static int |
166 | checkentry_v1(const char *tablename, | 168 | checkentry_v1(const char *tablename, |
167 | const struct ipt_ip *ip, | 169 | const void *ip, |
168 | void *matchinfo, | 170 | void *matchinfo, |
169 | unsigned int matchsize, | 171 | unsigned int matchsize, |
170 | unsigned int hook_mask) | 172 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c index 0cee2862ed85..4843d0c9734f 100644 --- a/net/ipv4/netfilter/ipt_owner.c +++ b/net/ipv4/netfilter/ipt_owner.c | |||
@@ -27,6 +27,7 @@ match(const struct sk_buff *skb, | |||
27 | const struct net_device *out, | 27 | const struct net_device *out, |
28 | const void *matchinfo, | 28 | const void *matchinfo, |
29 | int offset, | 29 | int offset, |
30 | unsigned int protoff, | ||
30 | int *hotdrop) | 31 | int *hotdrop) |
31 | { | 32 | { |
32 | const struct ipt_owner_info *info = matchinfo; | 33 | const struct ipt_owner_info *info = matchinfo; |
@@ -51,7 +52,7 @@ match(const struct sk_buff *skb, | |||
51 | 52 | ||
52 | static int | 53 | static int |
53 | checkentry(const char *tablename, | 54 | checkentry(const char *tablename, |
54 | const struct ipt_ip *ip, | 55 | const void *ip, |
55 | void *matchinfo, | 56 | void *matchinfo, |
56 | unsigned int matchsize, | 57 | unsigned int matchsize, |
57 | unsigned int hook_mask) | 58 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_physdev.c b/net/ipv4/netfilter/ipt_physdev.c deleted file mode 100644 index 03f554857a4d..000000000000 --- a/net/ipv4/netfilter/ipt_physdev.c +++ /dev/null | |||
@@ -1,135 +0,0 @@ | |||
1 | /* Kernel module to match the bridge port in and | ||
2 | * out device for IP packets coming into contact with a bridge. */ | ||
3 | |||
4 | /* (C) 2001-2003 Bart De Schuymer <bdschuym@pandora.be> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/netdevice.h> | ||
13 | #include <linux/skbuff.h> | ||
14 | #include <linux/netfilter_ipv4/ipt_physdev.h> | ||
15 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
16 | #include <linux/netfilter_bridge.h> | ||
17 | #define MATCH 1 | ||
18 | #define NOMATCH 0 | ||
19 | |||
20 | MODULE_LICENSE("GPL"); | ||
21 | MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); | ||
22 | MODULE_DESCRIPTION("iptables bridge physical device match module"); | ||
23 | |||
24 | static int | ||
25 | match(const struct sk_buff *skb, | ||
26 | const struct net_device *in, | ||
27 | const struct net_device *out, | ||
28 | const void *matchinfo, | ||
29 | int offset, | ||
30 | int *hotdrop) | ||
31 | { | ||
32 | int i; | ||
33 | static const char nulldevname[IFNAMSIZ]; | ||
34 | const struct ipt_physdev_info *info = matchinfo; | ||
35 | unsigned int ret; | ||
36 | const char *indev, *outdev; | ||
37 | struct nf_bridge_info *nf_bridge; | ||
38 | |||
39 | /* Not a bridged IP packet or no info available yet: | ||
40 | * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if | ||
41 | * the destination device will be a bridge. */ | ||
42 | if (!(nf_bridge = skb->nf_bridge)) { | ||
43 | /* Return MATCH if the invert flags of the used options are on */ | ||
44 | if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) && | ||
45 | !(info->invert & IPT_PHYSDEV_OP_BRIDGED)) | ||
46 | return NOMATCH; | ||
47 | if ((info->bitmask & IPT_PHYSDEV_OP_ISIN) && | ||
48 | !(info->invert & IPT_PHYSDEV_OP_ISIN)) | ||
49 | return NOMATCH; | ||
50 | if ((info->bitmask & IPT_PHYSDEV_OP_ISOUT) && | ||
51 | !(info->invert & IPT_PHYSDEV_OP_ISOUT)) | ||
52 | return NOMATCH; | ||
53 | if ((info->bitmask & IPT_PHYSDEV_OP_IN) && | ||
54 | !(info->invert & IPT_PHYSDEV_OP_IN)) | ||
55 | return NOMATCH; | ||
56 | if ((info->bitmask & IPT_PHYSDEV_OP_OUT) && | ||
57 | !(info->invert & IPT_PHYSDEV_OP_OUT)) | ||
58 | return NOMATCH; | ||
59 | return MATCH; | ||
60 | } | ||
61 | |||
62 | /* This only makes sense in the FORWARD and POSTROUTING chains */ | ||
63 | if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) && | ||
64 | (!!(nf_bridge->mask & BRNF_BRIDGED) ^ | ||
65 | !(info->invert & IPT_PHYSDEV_OP_BRIDGED))) | ||
66 | return NOMATCH; | ||
67 | |||
68 | if ((info->bitmask & IPT_PHYSDEV_OP_ISIN && | ||
69 | (!nf_bridge->physindev ^ !!(info->invert & IPT_PHYSDEV_OP_ISIN))) || | ||
70 | (info->bitmask & IPT_PHYSDEV_OP_ISOUT && | ||
71 | (!nf_bridge->physoutdev ^ !!(info->invert & IPT_PHYSDEV_OP_ISOUT)))) | ||
72 | return NOMATCH; | ||
73 | |||
74 | if (!(info->bitmask & IPT_PHYSDEV_OP_IN)) | ||
75 | goto match_outdev; | ||
76 | indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; | ||
77 | for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { | ||
78 | ret |= (((const unsigned int *)indev)[i] | ||
79 | ^ ((const unsigned int *)info->physindev)[i]) | ||
80 | & ((const unsigned int *)info->in_mask)[i]; | ||
81 | } | ||
82 | |||
83 | if ((ret == 0) ^ !(info->invert & IPT_PHYSDEV_OP_IN)) | ||
84 | return NOMATCH; | ||
85 | |||
86 | match_outdev: | ||
87 | if (!(info->bitmask & IPT_PHYSDEV_OP_OUT)) | ||
88 | return MATCH; | ||
89 | outdev = nf_bridge->physoutdev ? | ||
90 | nf_bridge->physoutdev->name : nulldevname; | ||
91 | for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { | ||
92 | ret |= (((const unsigned int *)outdev)[i] | ||
93 | ^ ((const unsigned int *)info->physoutdev)[i]) | ||
94 | & ((const unsigned int *)info->out_mask)[i]; | ||
95 | } | ||
96 | |||
97 | return (ret != 0) ^ !(info->invert & IPT_PHYSDEV_OP_OUT); | ||
98 | } | ||
99 | |||
100 | static int | ||
101 | checkentry(const char *tablename, | ||
102 | const struct ipt_ip *ip, | ||
103 | void *matchinfo, | ||
104 | unsigned int matchsize, | ||
105 | unsigned int hook_mask) | ||
106 | { | ||
107 | const struct ipt_physdev_info *info = matchinfo; | ||
108 | |||
109 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_physdev_info))) | ||
110 | return 0; | ||
111 | if (!(info->bitmask & IPT_PHYSDEV_OP_MASK) || | ||
112 | info->bitmask & ~IPT_PHYSDEV_OP_MASK) | ||
113 | return 0; | ||
114 | return 1; | ||
115 | } | ||
116 | |||
117 | static struct ipt_match physdev_match = { | ||
118 | .name = "physdev", | ||
119 | .match = &match, | ||
120 | .checkentry = &checkentry, | ||
121 | .me = THIS_MODULE, | ||
122 | }; | ||
123 | |||
124 | static int __init init(void) | ||
125 | { | ||
126 | return ipt_register_match(&physdev_match); | ||
127 | } | ||
128 | |||
129 | static void __exit fini(void) | ||
130 | { | ||
131 | ipt_unregister_match(&physdev_match); | ||
132 | } | ||
133 | |||
134 | module_init(init); | ||
135 | module_exit(fini); | ||
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c index 5ddccb18c65e..44611d6d14f5 100644 --- a/net/ipv4/netfilter/ipt_recent.c +++ b/net/ipv4/netfilter/ipt_recent.c | |||
@@ -104,6 +104,7 @@ match(const struct sk_buff *skb, | |||
104 | const struct net_device *out, | 104 | const struct net_device *out, |
105 | const void *matchinfo, | 105 | const void *matchinfo, |
106 | int offset, | 106 | int offset, |
107 | unsigned int protoff, | ||
107 | int *hotdrop); | 108 | int *hotdrop); |
108 | 109 | ||
109 | /* Function to hash a given address into the hash table of table_size size */ | 110 | /* Function to hash a given address into the hash table of table_size size */ |
@@ -317,7 +318,7 @@ static int ip_recent_ctrl(struct file *file, const char __user *input, unsigned | |||
317 | skb->nh.iph->daddr = 0; | 318 | skb->nh.iph->daddr = 0; |
318 | /* Clear ttl since we have no way of knowing it */ | 319 | /* Clear ttl since we have no way of knowing it */ |
319 | skb->nh.iph->ttl = 0; | 320 | skb->nh.iph->ttl = 0; |
320 | match(skb,NULL,NULL,info,0,NULL); | 321 | match(skb,NULL,NULL,info,0,0,NULL); |
321 | 322 | ||
322 | kfree(skb->nh.iph); | 323 | kfree(skb->nh.iph); |
323 | out_free_skb: | 324 | out_free_skb: |
@@ -357,6 +358,7 @@ match(const struct sk_buff *skb, | |||
357 | const struct net_device *out, | 358 | const struct net_device *out, |
358 | const void *matchinfo, | 359 | const void *matchinfo, |
359 | int offset, | 360 | int offset, |
361 | unsigned int protoff, | ||
360 | int *hotdrop) | 362 | int *hotdrop) |
361 | { | 363 | { |
362 | int pkt_count, hits_found, ans; | 364 | int pkt_count, hits_found, ans; |
@@ -654,7 +656,7 @@ match(const struct sk_buff *skb, | |||
654 | */ | 656 | */ |
655 | static int | 657 | static int |
656 | checkentry(const char *tablename, | 658 | checkentry(const char *tablename, |
657 | const struct ipt_ip *ip, | 659 | const void *ip, |
658 | void *matchinfo, | 660 | void *matchinfo, |
659 | unsigned int matchsize, | 661 | unsigned int matchsize, |
660 | unsigned int hook_mask) | 662 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c index 086a1bb61e3e..9ab765e126f2 100644 --- a/net/ipv4/netfilter/ipt_tos.c +++ b/net/ipv4/netfilter/ipt_tos.c | |||
@@ -23,6 +23,7 @@ match(const struct sk_buff *skb, | |||
23 | const struct net_device *out, | 23 | const struct net_device *out, |
24 | const void *matchinfo, | 24 | const void *matchinfo, |
25 | int offset, | 25 | int offset, |
26 | unsigned int protoff, | ||
26 | int *hotdrop) | 27 | int *hotdrop) |
27 | { | 28 | { |
28 | const struct ipt_tos_info *info = matchinfo; | 29 | const struct ipt_tos_info *info = matchinfo; |
@@ -32,7 +33,7 @@ match(const struct sk_buff *skb, | |||
32 | 33 | ||
33 | static int | 34 | static int |
34 | checkentry(const char *tablename, | 35 | checkentry(const char *tablename, |
35 | const struct ipt_ip *ip, | 36 | const void *ip, |
36 | void *matchinfo, | 37 | void *matchinfo, |
37 | unsigned int matchsize, | 38 | unsigned int matchsize, |
38 | unsigned int hook_mask) | 39 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c index 219aa9de88cc..82da53f430ab 100644 --- a/net/ipv4/netfilter/ipt_ttl.c +++ b/net/ipv4/netfilter/ipt_ttl.c | |||
@@ -21,7 +21,7 @@ MODULE_LICENSE("GPL"); | |||
21 | 21 | ||
22 | static int match(const struct sk_buff *skb, const struct net_device *in, | 22 | static int match(const struct sk_buff *skb, const struct net_device *in, |
23 | const struct net_device *out, const void *matchinfo, | 23 | const struct net_device *out, const void *matchinfo, |
24 | int offset, int *hotdrop) | 24 | int offset, unsigned int protoff, int *hotdrop) |
25 | { | 25 | { |
26 | const struct ipt_ttl_info *info = matchinfo; | 26 | const struct ipt_ttl_info *info = matchinfo; |
27 | 27 | ||
@@ -47,7 +47,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, | |||
47 | return 0; | 47 | return 0; |
48 | } | 48 | } |
49 | 49 | ||
50 | static int checkentry(const char *tablename, const struct ipt_ip *ip, | 50 | static int checkentry(const char *tablename, const void *ip, |
51 | void *matchinfo, unsigned int matchsize, | 51 | void *matchinfo, unsigned int matchsize, |
52 | unsigned int hook_mask) | 52 | unsigned int hook_mask) |
53 | { | 53 | { |
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 260a4f0a2a90..212a3079085b 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c | |||
@@ -78,7 +78,8 @@ static struct ipt_table packet_filter = { | |||
78 | .name = "filter", | 78 | .name = "filter", |
79 | .valid_hooks = FILTER_VALID_HOOKS, | 79 | .valid_hooks = FILTER_VALID_HOOKS, |
80 | .lock = RW_LOCK_UNLOCKED, | 80 | .lock = RW_LOCK_UNLOCKED, |
81 | .me = THIS_MODULE | 81 | .me = THIS_MODULE, |
82 | .af = AF_INET, | ||
82 | }; | 83 | }; |
83 | 84 | ||
84 | /* The work comes in here from netfilter.c. */ | 85 | /* The work comes in here from netfilter.c. */ |
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 160eb11b6e2f..3212a5cc4b6b 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c | |||
@@ -109,6 +109,7 @@ static struct ipt_table packet_mangler = { | |||
109 | .valid_hooks = MANGLE_VALID_HOOKS, | 109 | .valid_hooks = MANGLE_VALID_HOOKS, |
110 | .lock = RW_LOCK_UNLOCKED, | 110 | .lock = RW_LOCK_UNLOCKED, |
111 | .me = THIS_MODULE, | 111 | .me = THIS_MODULE, |
112 | .af = AF_INET, | ||
112 | }; | 113 | }; |
113 | 114 | ||
114 | /* The work comes in here from netfilter.c. */ | 115 | /* The work comes in here from netfilter.c. */ |
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 47449ba83eb9..fdb9e9c81e81 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c | |||
@@ -83,7 +83,8 @@ static struct ipt_table packet_raw = { | |||
83 | .name = "raw", | 83 | .name = "raw", |
84 | .valid_hooks = RAW_VALID_HOOKS, | 84 | .valid_hooks = RAW_VALID_HOOKS, |
85 | .lock = RW_LOCK_UNLOCKED, | 85 | .lock = RW_LOCK_UNLOCKED, |
86 | .me = THIS_MODULE | 86 | .me = THIS_MODULE, |
87 | .af = AF_INET, | ||
87 | }; | 88 | }; |
88 | 89 | ||
89 | /* The work comes in here from netfilter.c. */ | 90 | /* The work comes in here from netfilter.c. */ |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 0c56c52a3831..167619f638c6 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -575,7 +575,7 @@ MODULE_LICENSE("GPL"); | |||
575 | 575 | ||
576 | static int __init init(void) | 576 | static int __init init(void) |
577 | { | 577 | { |
578 | need_nf_conntrack(); | 578 | need_conntrack(); |
579 | return init_or_cleanup(1); | 579 | return init_or_cleanup(1); |
580 | } | 580 | } |
581 | 581 | ||
@@ -587,9 +587,4 @@ static void __exit fini(void) | |||
587 | module_init(init); | 587 | module_init(init); |
588 | module_exit(fini); | 588 | module_exit(fini); |
589 | 589 | ||
590 | void need_ip_conntrack(void) | ||
591 | { | ||
592 | } | ||
593 | |||
594 | EXPORT_SYMBOL(need_ip_conntrack); | ||
595 | EXPORT_SYMBOL(nf_ct_ipv4_gather_frags); | 590 | EXPORT_SYMBOL(nf_ct_ipv4_gather_frags); |
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index d23e07fc81fa..dbabf81a9b7b 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
@@ -42,6 +42,21 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
42 | x->props.saddr = tmpl->saddr; | 42 | x->props.saddr = tmpl->saddr; |
43 | if (x->props.saddr.a4 == 0) | 43 | if (x->props.saddr.a4 == 0) |
44 | x->props.saddr.a4 = saddr->a4; | 44 | x->props.saddr.a4 = saddr->a4; |
45 | if (tmpl->mode && x->props.saddr.a4 == 0) { | ||
46 | struct rtable *rt; | ||
47 | struct flowi fl_tunnel = { | ||
48 | .nl_u = { | ||
49 | .ip4_u = { | ||
50 | .daddr = x->id.daddr.a4, | ||
51 | } | ||
52 | } | ||
53 | }; | ||
54 | if (!xfrm_dst_lookup((struct xfrm_dst **)&rt, | ||
55 | &fl_tunnel, AF_INET)) { | ||
56 | x->props.saddr.a4 = rt->rt_src; | ||
57 | dst_release(&rt->u.dst); | ||
58 | } | ||
59 | } | ||
45 | x->props.mode = tmpl->mode; | 60 | x->props.mode = tmpl->mode; |
46 | x->props.reqid = tmpl->reqid; | 61 | x->props.reqid = tmpl->reqid; |
47 | x->props.family = AF_INET; | 62 | x->props.family = AF_INET; |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 7129d4239755..dfb4f145a139 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -2644,7 +2644,7 @@ static int if6_seq_show(struct seq_file *seq, void *v) | |||
2644 | { | 2644 | { |
2645 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v; | 2645 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v; |
2646 | seq_printf(seq, | 2646 | seq_printf(seq, |
2647 | "%04x%04x%04x%04x%04x%04x%04x%04x %02x %02x %02x %02x %8s\n", | 2647 | NIP6_FMT " %02x %02x %02x %02x %8s\n", |
2648 | NIP6(ifp->addr), | 2648 | NIP6(ifp->addr), |
2649 | ifp->idev->dev->ifindex, | 2649 | ifp->idev->dev->ifindex, |
2650 | ifp->prefix_len, | 2650 | ifp->prefix_len, |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 13cc7f895583..c7932cb420a5 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -332,8 +332,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
332 | if (!x) | 332 | if (!x) |
333 | return; | 333 | return; |
334 | 334 | ||
335 | NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/" | 335 | NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/" NIP6_FMT "\n", |
336 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
337 | ntohl(ah->spi), NIP6(iph->daddr)); | 336 | ntohl(ah->spi), NIP6(iph->daddr)); |
338 | 337 | ||
339 | xfrm_state_put(x); | 338 | xfrm_state_put(x); |
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 65e73ac0d6d0..72bd08af2dfb 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -532,9 +532,7 @@ static int ac6_seq_show(struct seq_file *seq, void *v) | |||
532 | struct ac6_iter_state *state = ac6_seq_private(seq); | 532 | struct ac6_iter_state *state = ac6_seq_private(seq); |
533 | 533 | ||
534 | seq_printf(seq, | 534 | seq_printf(seq, |
535 | "%-4d %-15s " | 535 | "%-4d %-15s " NIP6_FMT " %5d\n", |
536 | "%04x%04x%04x%04x%04x%04x%04x%04x " | ||
537 | "%5d\n", | ||
538 | state->dev->ifindex, state->dev->name, | 536 | state->dev->ifindex, state->dev->name, |
539 | NIP6(im->aca_addr), | 537 | NIP6(im->aca_addr), |
540 | im->aca_users); | 538 | im->aca_users); |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 6de8ee1a5ad9..7b5b94f13902 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -266,8 +266,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
266 | x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6); | 266 | x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6); |
267 | if (!x) | 267 | if (!x) |
268 | return; | 268 | return; |
269 | printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/" | 269 | printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/" NIP6_FMT "\n", |
270 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
271 | ntohl(esph->spi), NIP6(iph->daddr)); | 270 | ntohl(esph->spi), NIP6(iph->daddr)); |
272 | xfrm_state_put(x); | 271 | xfrm_state_put(x); |
273 | } | 272 | } |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 53c81fcd20ba..fcf883183cef 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -607,7 +607,7 @@ static int icmpv6_rcv(struct sk_buff **pskb) | |||
607 | skb->csum = ~csum_ipv6_magic(saddr, daddr, skb->len, | 607 | skb->csum = ~csum_ipv6_magic(saddr, daddr, skb->len, |
608 | IPPROTO_ICMPV6, 0); | 608 | IPPROTO_ICMPV6, 0); |
609 | if (__skb_checksum_complete(skb)) { | 609 | if (__skb_checksum_complete(skb)) { |
610 | LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n", | 610 | LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [" NIP6_FMT " > " NIP6_FMT "]\n", |
611 | NIP6(*saddr), NIP6(*daddr)); | 611 | NIP6(*saddr), NIP6(*daddr)); |
612 | goto discard_it; | 612 | goto discard_it; |
613 | } | 613 | } |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 964ad9d1276d..4183c8dac7f6 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -629,9 +629,7 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) | |||
629 | { | 629 | { |
630 | while(fl) { | 630 | while(fl) { |
631 | seq_printf(seq, | 631 | seq_printf(seq, |
632 | "%05X %-1d %-6d %-6d %-6ld %-8ld " | 632 | "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_FMT " %-4d\n", |
633 | "%02x%02x%02x%02x%02x%02x%02x%02x " | ||
634 | "%-4d\n", | ||
635 | (unsigned)ntohl(fl->label), | 633 | (unsigned)ntohl(fl->label), |
636 | fl->share, | 634 | fl->share, |
637 | (unsigned)fl->owner, | 635 | (unsigned)fl->owner, |
@@ -647,8 +645,8 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) | |||
647 | static int ip6fl_seq_show(struct seq_file *seq, void *v) | 645 | static int ip6fl_seq_show(struct seq_file *seq, void *v) |
648 | { | 646 | { |
649 | if (v == SEQ_START_TOKEN) | 647 | if (v == SEQ_START_TOKEN) |
650 | seq_puts(seq, "Label S Owner Users Linger Expires " | 648 | seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-39s %s\n", |
651 | "Dst Opt\n"); | 649 | "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); |
652 | else | 650 | else |
653 | ip6fl_fl_seq_show(seq, v); | 651 | ip6fl_fl_seq_show(seq, v); |
654 | return 0; | 652 | return 0; |
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 626dd39685f2..d511a884dad0 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
@@ -212,8 +212,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
212 | if (!x) | 212 | if (!x) |
213 | return; | 213 | return; |
214 | 214 | ||
215 | printk(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/" | 215 | printk(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/" NIP6_FMT "\n", |
216 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
217 | spi, NIP6(iph->daddr)); | 216 | spi, NIP6(iph->daddr)); |
218 | xfrm_state_put(x); | 217 | xfrm_state_put(x); |
219 | } | 218 | } |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index cc3e9f560867..0e03eabfb9da 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -2373,7 +2373,7 @@ static int igmp6_mc_seq_show(struct seq_file *seq, void *v) | |||
2373 | struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq); | 2373 | struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq); |
2374 | 2374 | ||
2375 | seq_printf(seq, | 2375 | seq_printf(seq, |
2376 | "%-4d %-15s %04x%04x%04x%04x%04x%04x%04x%04x %5d %08X %ld\n", | 2376 | "%-4d %-15s " NIP6_FMT " %5d %08X %ld\n", |
2377 | state->dev->ifindex, state->dev->name, | 2377 | state->dev->ifindex, state->dev->name, |
2378 | NIP6(im->mca_addr), | 2378 | NIP6(im->mca_addr), |
2379 | im->mca_users, im->mca_flags, | 2379 | im->mca_users, im->mca_flags, |
@@ -2542,15 +2542,12 @@ static int igmp6_mcf_seq_show(struct seq_file *seq, void *v) | |||
2542 | if (v == SEQ_START_TOKEN) { | 2542 | if (v == SEQ_START_TOKEN) { |
2543 | seq_printf(seq, | 2543 | seq_printf(seq, |
2544 | "%3s %6s " | 2544 | "%3s %6s " |
2545 | "%32s %32s %6s %6s\n", "Idx", | 2545 | "%39s %39s %6s %6s\n", "Idx", |
2546 | "Device", "Multicast Address", | 2546 | "Device", "Multicast Address", |
2547 | "Source Address", "INC", "EXC"); | 2547 | "Source Address", "INC", "EXC"); |
2548 | } else { | 2548 | } else { |
2549 | seq_printf(seq, | 2549 | seq_printf(seq, |
2550 | "%3d %6.6s " | 2550 | "%3d %6.6s " NIP6_FMT " " NIP6_FMT " %6lu %6lu\n", |
2551 | "%04x%04x%04x%04x%04x%04x%04x%04x " | ||
2552 | "%04x%04x%04x%04x%04x%04x%04x%04x " | ||
2553 | "%6lu %6lu\n", | ||
2554 | state->dev->ifindex, state->dev->name, | 2551 | state->dev->ifindex, state->dev->name, |
2555 | NIP6(state->im->mca_addr), | 2552 | NIP6(state->im->mca_addr), |
2556 | NIP6(psf->sf_addr), | 2553 | NIP6(psf->sf_addr), |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 305d9ee6d7db..cb8856b1d951 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -692,7 +692,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
692 | if (!(neigh->nud_state & NUD_VALID)) { | 692 | if (!(neigh->nud_state & NUD_VALID)) { |
693 | ND_PRINTK1(KERN_DEBUG | 693 | ND_PRINTK1(KERN_DEBUG |
694 | "%s(): trying to ucast probe in NUD_INVALID: " | 694 | "%s(): trying to ucast probe in NUD_INVALID: " |
695 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | 695 | NIP6_FMT "\n", |
696 | __FUNCTION__, | 696 | __FUNCTION__, |
697 | NIP6(*target)); | 697 | NIP6(*target)); |
698 | } | 698 | } |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 105dd69ee9fb..2d6f8ecbc27b 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -41,6 +41,7 @@ config IP6_NF_QUEUE | |||
41 | 41 | ||
42 | config IP6_NF_IPTABLES | 42 | config IP6_NF_IPTABLES |
43 | tristate "IP6 tables support (required for filtering/masq/NAT)" | 43 | tristate "IP6 tables support (required for filtering/masq/NAT)" |
44 | depends on NETFILTER_XTABLES | ||
44 | help | 45 | help |
45 | ip6tables is a general, extensible packet identification framework. | 46 | ip6tables is a general, extensible packet identification framework. |
46 | Currently only the packet filtering and packet mangling subsystem | 47 | Currently only the packet filtering and packet mangling subsystem |
@@ -50,25 +51,6 @@ config IP6_NF_IPTABLES | |||
50 | To compile it as a module, choose M here. If unsure, say N. | 51 | To compile it as a module, choose M here. If unsure, say N. |
51 | 52 | ||
52 | # The simple matches. | 53 | # The simple matches. |
53 | config IP6_NF_MATCH_LIMIT | ||
54 | tristate "limit match support" | ||
55 | depends on IP6_NF_IPTABLES | ||
56 | help | ||
57 | limit matching allows you to control the rate at which a rule can be | ||
58 | matched: mainly useful in combination with the LOG target ("LOG | ||
59 | target support", below) and to avoid some Denial of Service attacks. | ||
60 | |||
61 | To compile it as a module, choose M here. If unsure, say N. | ||
62 | |||
63 | config IP6_NF_MATCH_MAC | ||
64 | tristate "MAC address match support" | ||
65 | depends on IP6_NF_IPTABLES | ||
66 | help | ||
67 | mac matching allows you to match packets based on the source | ||
68 | Ethernet address of the packet. | ||
69 | |||
70 | To compile it as a module, choose M here. If unsure, say N. | ||
71 | |||
72 | config IP6_NF_MATCH_RT | 54 | config IP6_NF_MATCH_RT |
73 | tristate "Routing header match support" | 55 | tristate "Routing header match support" |
74 | depends on IP6_NF_IPTABLES | 56 | depends on IP6_NF_IPTABLES |
@@ -124,16 +106,6 @@ config IP6_NF_MATCH_OWNER | |||
124 | 106 | ||
125 | To compile it as a module, choose M here. If unsure, say N. | 107 | To compile it as a module, choose M here. If unsure, say N. |
126 | 108 | ||
127 | config IP6_NF_MATCH_MARK | ||
128 | tristate "netfilter MARK match support" | ||
129 | depends on IP6_NF_IPTABLES | ||
130 | help | ||
131 | Netfilter mark matching allows you to match packets based on the | ||
132 | `nfmark' value in the packet. This can be set by the MARK target | ||
133 | (see below). | ||
134 | |||
135 | To compile it as a module, choose M here. If unsure, say N. | ||
136 | |||
137 | config IP6_NF_MATCH_IPV6HEADER | 109 | config IP6_NF_MATCH_IPV6HEADER |
138 | tristate "IPv6 Extension Headers Match" | 110 | tristate "IPv6 Extension Headers Match" |
139 | depends on IP6_NF_IPTABLES | 111 | depends on IP6_NF_IPTABLES |
@@ -151,15 +123,6 @@ config IP6_NF_MATCH_AHESP | |||
151 | 123 | ||
152 | To compile it as a module, choose M here. If unsure, say N. | 124 | To compile it as a module, choose M here. If unsure, say N. |
153 | 125 | ||
154 | config IP6_NF_MATCH_LENGTH | ||
155 | tristate "Packet Length match support" | ||
156 | depends on IP6_NF_IPTABLES | ||
157 | help | ||
158 | This option allows you to match the length of a packet against a | ||
159 | specific value or range of values. | ||
160 | |||
161 | To compile it as a module, choose M here. If unsure, say N. | ||
162 | |||
163 | config IP6_NF_MATCH_EUI64 | 126 | config IP6_NF_MATCH_EUI64 |
164 | tristate "EUI64 address check" | 127 | tristate "EUI64 address check" |
165 | depends on IP6_NF_IPTABLES | 128 | depends on IP6_NF_IPTABLES |
@@ -170,15 +133,6 @@ config IP6_NF_MATCH_EUI64 | |||
170 | 133 | ||
171 | To compile it as a module, choose M here. If unsure, say N. | 134 | To compile it as a module, choose M here. If unsure, say N. |
172 | 135 | ||
173 | config IP6_NF_MATCH_PHYSDEV | ||
174 | tristate "Physdev match support" | ||
175 | depends on IP6_NF_IPTABLES && BRIDGE_NETFILTER | ||
176 | help | ||
177 | Physdev packet matching matches against the physical bridge ports | ||
178 | the IP packet arrived on or will leave by. | ||
179 | |||
180 | To compile it as a module, choose M here. If unsure, say N. | ||
181 | |||
182 | config IP6_NF_MATCH_POLICY | 136 | config IP6_NF_MATCH_POLICY |
183 | tristate "IPsec policy match support" | 137 | tristate "IPsec policy match support" |
184 | depends on IP6_NF_IPTABLES && XFRM | 138 | depends on IP6_NF_IPTABLES && XFRM |
@@ -219,17 +173,6 @@ config IP6_NF_TARGET_REJECT | |||
219 | 173 | ||
220 | To compile it as a module, choose M here. If unsure, say N. | 174 | To compile it as a module, choose M here. If unsure, say N. |
221 | 175 | ||
222 | config IP6_NF_TARGET_NFQUEUE | ||
223 | tristate "NFQUEUE Target Support" | ||
224 | depends on IP6_NF_IPTABLES | ||
225 | help | ||
226 | This Target replaced the old obsolete QUEUE target. | ||
227 | |||
228 | As opposed to QUEUE, it supports 65535 different queues, | ||
229 | not just one. | ||
230 | |||
231 | To compile it as a module, choose M here. If unsure, say N. | ||
232 | |||
233 | config IP6_NF_MANGLE | 176 | config IP6_NF_MANGLE |
234 | tristate "Packet mangling" | 177 | tristate "Packet mangling" |
235 | depends on IP6_NF_IPTABLES | 178 | depends on IP6_NF_IPTABLES |
@@ -240,19 +183,6 @@ config IP6_NF_MANGLE | |||
240 | 183 | ||
241 | To compile it as a module, choose M here. If unsure, say N. | 184 | To compile it as a module, choose M here. If unsure, say N. |
242 | 185 | ||
243 | config IP6_NF_TARGET_MARK | ||
244 | tristate "MARK target support" | ||
245 | depends on IP6_NF_MANGLE | ||
246 | help | ||
247 | This option adds a `MARK' target, which allows you to create rules | ||
248 | in the `mangle' table which alter the netfilter mark (nfmark) field | ||
249 | associated with the packet packet prior to routing. This can change | ||
250 | the routing method (see `Use netfilter MARK value as routing | ||
251 | key') and can also be used by other subsystems to change their | ||
252 | behavior. | ||
253 | |||
254 | To compile it as a module, choose M here. If unsure, say N. | ||
255 | |||
256 | config IP6_NF_TARGET_HL | 186 | config IP6_NF_TARGET_HL |
257 | tristate 'HL (hoplimit) target support' | 187 | tristate 'HL (hoplimit) target support' |
258 | depends on IP6_NF_MANGLE | 188 | depends on IP6_NF_MANGLE |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index c0c809b426e8..663b4749820d 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -4,10 +4,7 @@ | |||
4 | 4 | ||
5 | # Link order matters here. | 5 | # Link order matters here. |
6 | obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o | 6 | obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o |
7 | obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o | ||
8 | obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o | ||
9 | obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o | 7 | obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o |
10 | obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o | ||
11 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o | 8 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o |
12 | obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o | 9 | obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o |
13 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o | 10 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o |
@@ -17,12 +14,9 @@ obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o | |||
17 | obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o | 14 | obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o |
18 | obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o | 15 | obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o |
19 | obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o | 16 | obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o |
20 | obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o | ||
21 | obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o | 17 | obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o |
22 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o | 18 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o |
23 | obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o | ||
24 | obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o | 19 | obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o |
25 | obj-$(CONFIG_IP6_NF_TARGET_NFQUEUE) += ip6t_NFQUEUE.o | ||
26 | obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o | 20 | obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o |
27 | obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o | 21 | obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o |
28 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o | 22 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 1390370186d9..847068fd3367 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -13,6 +13,9 @@ | |||
13 | * a table | 13 | * a table |
14 | * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu> | 14 | * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu> |
15 | * - new extension header parser code | 15 | * - new extension header parser code |
16 | * 15 Oct 2005 Harald Welte <laforge@netfilter.org> | ||
17 | * - Unification of {ip,ip6}_tables into x_tables | ||
18 | * - Removed tcp and udp code, since it's not ipv6 specific | ||
16 | */ | 19 | */ |
17 | 20 | ||
18 | #include <linux/capability.h> | 21 | #include <linux/capability.h> |
@@ -23,8 +26,6 @@ | |||
23 | #include <linux/vmalloc.h> | 26 | #include <linux/vmalloc.h> |
24 | #include <linux/netdevice.h> | 27 | #include <linux/netdevice.h> |
25 | #include <linux/module.h> | 28 | #include <linux/module.h> |
26 | #include <linux/tcp.h> | ||
27 | #include <linux/udp.h> | ||
28 | #include <linux/icmpv6.h> | 29 | #include <linux/icmpv6.h> |
29 | #include <net/ipv6.h> | 30 | #include <net/ipv6.h> |
30 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
@@ -33,6 +34,7 @@ | |||
33 | #include <linux/cpumask.h> | 34 | #include <linux/cpumask.h> |
34 | 35 | ||
35 | #include <linux/netfilter_ipv6/ip6_tables.h> | 36 | #include <linux/netfilter_ipv6/ip6_tables.h> |
37 | #include <linux/netfilter/x_tables.h> | ||
36 | 38 | ||
37 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
38 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | 40 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); |
@@ -67,13 +69,8 @@ do { \ | |||
67 | #else | 69 | #else |
68 | #define IP_NF_ASSERT(x) | 70 | #define IP_NF_ASSERT(x) |
69 | #endif | 71 | #endif |
70 | #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) | ||
71 | 72 | ||
72 | static DECLARE_MUTEX(ip6t_mutex); | ||
73 | 73 | ||
74 | /* Must have mutex */ | ||
75 | #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0) | ||
76 | #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0) | ||
77 | #include <linux/netfilter_ipv4/listhelp.h> | 74 | #include <linux/netfilter_ipv4/listhelp.h> |
78 | 75 | ||
79 | #if 0 | 76 | #if 0 |
@@ -91,30 +88,6 @@ static DECLARE_MUTEX(ip6t_mutex); | |||
91 | 88 | ||
92 | Hence the start of any table is given by get_table() below. */ | 89 | Hence the start of any table is given by get_table() below. */ |
93 | 90 | ||
94 | /* The table itself */ | ||
95 | struct ip6t_table_info | ||
96 | { | ||
97 | /* Size per table */ | ||
98 | unsigned int size; | ||
99 | /* Number of entries: FIXME. --RR */ | ||
100 | unsigned int number; | ||
101 | /* Initial number of entries. Needed for module usage count */ | ||
102 | unsigned int initial_entries; | ||
103 | |||
104 | /* Entry points and underflows */ | ||
105 | unsigned int hook_entry[NF_IP6_NUMHOOKS]; | ||
106 | unsigned int underflow[NF_IP6_NUMHOOKS]; | ||
107 | |||
108 | /* ip6t_entry tables: one per CPU */ | ||
109 | void *entries[NR_CPUS]; | ||
110 | }; | ||
111 | |||
112 | static LIST_HEAD(ip6t_target); | ||
113 | static LIST_HEAD(ip6t_match); | ||
114 | static LIST_HEAD(ip6t_tables); | ||
115 | #define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) | ||
116 | #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) | ||
117 | |||
118 | #if 0 | 91 | #if 0 |
119 | #define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0) | 92 | #define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0) |
120 | #define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; }) | 93 | #define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; }) |
@@ -297,7 +270,7 @@ ip6t_do_table(struct sk_buff **pskb, | |||
297 | unsigned int hook, | 270 | unsigned int hook, |
298 | const struct net_device *in, | 271 | const struct net_device *in, |
299 | const struct net_device *out, | 272 | const struct net_device *out, |
300 | struct ip6t_table *table, | 273 | struct xt_table *table, |
301 | void *userdata) | 274 | void *userdata) |
302 | { | 275 | { |
303 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); | 276 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); |
@@ -309,6 +282,7 @@ ip6t_do_table(struct sk_buff **pskb, | |||
309 | const char *indev, *outdev; | 282 | const char *indev, *outdev; |
310 | void *table_base; | 283 | void *table_base; |
311 | struct ip6t_entry *e, *back; | 284 | struct ip6t_entry *e, *back; |
285 | struct xt_table_info *private; | ||
312 | 286 | ||
313 | /* Initialization */ | 287 | /* Initialization */ |
314 | indev = in ? in->name : nulldevname; | 288 | indev = in ? in->name : nulldevname; |
@@ -321,9 +295,10 @@ ip6t_do_table(struct sk_buff **pskb, | |||
321 | * match it. */ | 295 | * match it. */ |
322 | 296 | ||
323 | read_lock_bh(&table->lock); | 297 | read_lock_bh(&table->lock); |
298 | private = table->private; | ||
324 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | 299 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
325 | table_base = (void *)table->private->entries[smp_processor_id()]; | 300 | table_base = (void *)private->entries[smp_processor_id()]; |
326 | e = get_entry(table_base, table->private->hook_entry[hook]); | 301 | e = get_entry(table_base, private->hook_entry[hook]); |
327 | 302 | ||
328 | #ifdef CONFIG_NETFILTER_DEBUG | 303 | #ifdef CONFIG_NETFILTER_DEBUG |
329 | /* Check noone else using our table */ | 304 | /* Check noone else using our table */ |
@@ -339,7 +314,7 @@ ip6t_do_table(struct sk_buff **pskb, | |||
339 | #endif | 314 | #endif |
340 | 315 | ||
341 | /* For return from builtin chain */ | 316 | /* For return from builtin chain */ |
342 | back = get_entry(table_base, table->private->underflow[hook]); | 317 | back = get_entry(table_base, private->underflow[hook]); |
343 | 318 | ||
344 | do { | 319 | do { |
345 | IP_NF_ASSERT(e); | 320 | IP_NF_ASSERT(e); |
@@ -439,145 +414,6 @@ ip6t_do_table(struct sk_buff **pskb, | |||
439 | #endif | 414 | #endif |
440 | } | 415 | } |
441 | 416 | ||
442 | /* | ||
443 | * These are weird, but module loading must not be done with mutex | ||
444 | * held (since they will register), and we have to have a single | ||
445 | * function to use try_then_request_module(). | ||
446 | */ | ||
447 | |||
448 | /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ | ||
449 | static inline struct ip6t_table *find_table_lock(const char *name) | ||
450 | { | ||
451 | struct ip6t_table *t; | ||
452 | |||
453 | if (down_interruptible(&ip6t_mutex) != 0) | ||
454 | return ERR_PTR(-EINTR); | ||
455 | |||
456 | list_for_each_entry(t, &ip6t_tables, list) | ||
457 | if (strcmp(t->name, name) == 0 && try_module_get(t->me)) | ||
458 | return t; | ||
459 | up(&ip6t_mutex); | ||
460 | return NULL; | ||
461 | } | ||
462 | |||
463 | /* Find match, grabs ref. Returns ERR_PTR() on error. */ | ||
464 | static inline struct ip6t_match *find_match(const char *name, u8 revision) | ||
465 | { | ||
466 | struct ip6t_match *m; | ||
467 | int err = 0; | ||
468 | |||
469 | if (down_interruptible(&ip6t_mutex) != 0) | ||
470 | return ERR_PTR(-EINTR); | ||
471 | |||
472 | list_for_each_entry(m, &ip6t_match, list) { | ||
473 | if (strcmp(m->name, name) == 0) { | ||
474 | if (m->revision == revision) { | ||
475 | if (try_module_get(m->me)) { | ||
476 | up(&ip6t_mutex); | ||
477 | return m; | ||
478 | } | ||
479 | } else | ||
480 | err = -EPROTOTYPE; /* Found something. */ | ||
481 | } | ||
482 | } | ||
483 | up(&ip6t_mutex); | ||
484 | return ERR_PTR(err); | ||
485 | } | ||
486 | |||
487 | /* Find target, grabs ref. Returns ERR_PTR() on error. */ | ||
488 | static inline struct ip6t_target *find_target(const char *name, u8 revision) | ||
489 | { | ||
490 | struct ip6t_target *t; | ||
491 | int err = 0; | ||
492 | |||
493 | if (down_interruptible(&ip6t_mutex) != 0) | ||
494 | return ERR_PTR(-EINTR); | ||
495 | |||
496 | list_for_each_entry(t, &ip6t_target, list) { | ||
497 | if (strcmp(t->name, name) == 0) { | ||
498 | if (t->revision == revision) { | ||
499 | if (try_module_get(t->me)) { | ||
500 | up(&ip6t_mutex); | ||
501 | return t; | ||
502 | } | ||
503 | } else | ||
504 | err = -EPROTOTYPE; /* Found something. */ | ||
505 | } | ||
506 | } | ||
507 | up(&ip6t_mutex); | ||
508 | return ERR_PTR(err); | ||
509 | } | ||
510 | |||
511 | struct ip6t_target *ip6t_find_target(const char *name, u8 revision) | ||
512 | { | ||
513 | struct ip6t_target *target; | ||
514 | |||
515 | target = try_then_request_module(find_target(name, revision), | ||
516 | "ip6t_%s", name); | ||
517 | if (IS_ERR(target) || !target) | ||
518 | return NULL; | ||
519 | return target; | ||
520 | } | ||
521 | |||
522 | static int match_revfn(const char *name, u8 revision, int *bestp) | ||
523 | { | ||
524 | struct ip6t_match *m; | ||
525 | int have_rev = 0; | ||
526 | |||
527 | list_for_each_entry(m, &ip6t_match, list) { | ||
528 | if (strcmp(m->name, name) == 0) { | ||
529 | if (m->revision > *bestp) | ||
530 | *bestp = m->revision; | ||
531 | if (m->revision == revision) | ||
532 | have_rev = 1; | ||
533 | } | ||
534 | } | ||
535 | return have_rev; | ||
536 | } | ||
537 | |||
538 | static int target_revfn(const char *name, u8 revision, int *bestp) | ||
539 | { | ||
540 | struct ip6t_target *t; | ||
541 | int have_rev = 0; | ||
542 | |||
543 | list_for_each_entry(t, &ip6t_target, list) { | ||
544 | if (strcmp(t->name, name) == 0) { | ||
545 | if (t->revision > *bestp) | ||
546 | *bestp = t->revision; | ||
547 | if (t->revision == revision) | ||
548 | have_rev = 1; | ||
549 | } | ||
550 | } | ||
551 | return have_rev; | ||
552 | } | ||
553 | |||
554 | /* Returns true or fals (if no such extension at all) */ | ||
555 | static inline int find_revision(const char *name, u8 revision, | ||
556 | int (*revfn)(const char *, u8, int *), | ||
557 | int *err) | ||
558 | { | ||
559 | int have_rev, best = -1; | ||
560 | |||
561 | if (down_interruptible(&ip6t_mutex) != 0) { | ||
562 | *err = -EINTR; | ||
563 | return 1; | ||
564 | } | ||
565 | have_rev = revfn(name, revision, &best); | ||
566 | up(&ip6t_mutex); | ||
567 | |||
568 | /* Nothing at all? Return 0 to try loading module. */ | ||
569 | if (best == -1) { | ||
570 | *err = -ENOENT; | ||
571 | return 0; | ||
572 | } | ||
573 | |||
574 | *err = best; | ||
575 | if (!have_rev) | ||
576 | *err = -EPROTONOSUPPORT; | ||
577 | return 1; | ||
578 | } | ||
579 | |||
580 | |||
581 | /* All zeroes == unconditional rule. */ | 417 | /* All zeroes == unconditional rule. */ |
582 | static inline int | 418 | static inline int |
583 | unconditional(const struct ip6t_ip6 *ipv6) | 419 | unconditional(const struct ip6t_ip6 *ipv6) |
@@ -594,7 +430,7 @@ unconditional(const struct ip6t_ip6 *ipv6) | |||
594 | /* Figures out from what hook each rule can be called: returns 0 if | 430 | /* Figures out from what hook each rule can be called: returns 0 if |
595 | there are loops. Puts hook bitmask in comefrom. */ | 431 | there are loops. Puts hook bitmask in comefrom. */ |
596 | static int | 432 | static int |
597 | mark_source_chains(struct ip6t_table_info *newinfo, | 433 | mark_source_chains(struct xt_table_info *newinfo, |
598 | unsigned int valid_hooks, void *entry0) | 434 | unsigned int valid_hooks, void *entry0) |
599 | { | 435 | { |
600 | unsigned int hook; | 436 | unsigned int hook; |
@@ -740,11 +576,11 @@ check_match(struct ip6t_entry_match *m, | |||
740 | { | 576 | { |
741 | struct ip6t_match *match; | 577 | struct ip6t_match *match; |
742 | 578 | ||
743 | match = try_then_request_module(find_match(m->u.user.name, | 579 | match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name, |
744 | m->u.user.revision), | 580 | m->u.user.revision), |
745 | "ip6t_%s", m->u.user.name); | 581 | "ip6t_%s", m->u.user.name); |
746 | if (IS_ERR(match) || !match) { | 582 | if (IS_ERR(match) || !match) { |
747 | duprintf("check_match: `%s' not found\n", m->u.user.name); | 583 | duprintf("check_match: `%s' not found\n", m->u.user.name); |
748 | return match ? PTR_ERR(match) : -ENOENT; | 584 | return match ? PTR_ERR(match) : -ENOENT; |
749 | } | 585 | } |
750 | m->u.kernel.match = match; | 586 | m->u.kernel.match = match; |
@@ -785,8 +621,9 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size, | |||
785 | goto cleanup_matches; | 621 | goto cleanup_matches; |
786 | 622 | ||
787 | t = ip6t_get_target(e); | 623 | t = ip6t_get_target(e); |
788 | target = try_then_request_module(find_target(t->u.user.name, | 624 | target = try_then_request_module(xt_find_target(AF_INET6, |
789 | t->u.user.revision), | 625 | t->u.user.name, |
626 | t->u.user.revision), | ||
790 | "ip6t_%s", t->u.user.name); | 627 | "ip6t_%s", t->u.user.name); |
791 | if (IS_ERR(target) || !target) { | 628 | if (IS_ERR(target) || !target) { |
792 | duprintf("check_entry: `%s' not found\n", t->u.user.name); | 629 | duprintf("check_entry: `%s' not found\n", t->u.user.name); |
@@ -822,7 +659,7 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size, | |||
822 | 659 | ||
823 | static inline int | 660 | static inline int |
824 | check_entry_size_and_hooks(struct ip6t_entry *e, | 661 | check_entry_size_and_hooks(struct ip6t_entry *e, |
825 | struct ip6t_table_info *newinfo, | 662 | struct xt_table_info *newinfo, |
826 | unsigned char *base, | 663 | unsigned char *base, |
827 | unsigned char *limit, | 664 | unsigned char *limit, |
828 | const unsigned int *hook_entries, | 665 | const unsigned int *hook_entries, |
@@ -856,7 +693,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e, | |||
856 | < 0 (not IP6T_RETURN). --RR */ | 693 | < 0 (not IP6T_RETURN). --RR */ |
857 | 694 | ||
858 | /* Clear counters and comefrom */ | 695 | /* Clear counters and comefrom */ |
859 | e->counters = ((struct ip6t_counters) { 0, 0 }); | 696 | e->counters = ((struct xt_counters) { 0, 0 }); |
860 | e->comefrom = 0; | 697 | e->comefrom = 0; |
861 | 698 | ||
862 | (*i)++; | 699 | (*i)++; |
@@ -886,7 +723,7 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i) | |||
886 | static int | 723 | static int |
887 | translate_table(const char *name, | 724 | translate_table(const char *name, |
888 | unsigned int valid_hooks, | 725 | unsigned int valid_hooks, |
889 | struct ip6t_table_info *newinfo, | 726 | struct xt_table_info *newinfo, |
890 | void *entry0, | 727 | void *entry0, |
891 | unsigned int size, | 728 | unsigned int size, |
892 | unsigned int number, | 729 | unsigned int number, |
@@ -963,48 +800,10 @@ translate_table(const char *name, | |||
963 | return ret; | 800 | return ret; |
964 | } | 801 | } |
965 | 802 | ||
966 | static struct ip6t_table_info * | ||
967 | replace_table(struct ip6t_table *table, | ||
968 | unsigned int num_counters, | ||
969 | struct ip6t_table_info *newinfo, | ||
970 | int *error) | ||
971 | { | ||
972 | struct ip6t_table_info *oldinfo; | ||
973 | |||
974 | #ifdef CONFIG_NETFILTER_DEBUG | ||
975 | { | ||
976 | int cpu; | ||
977 | |||
978 | for_each_cpu(cpu) { | ||
979 | struct ip6t_entry *table_base = newinfo->entries[cpu]; | ||
980 | if (table_base) | ||
981 | table_base->comefrom = 0xdead57ac; | ||
982 | } | ||
983 | } | ||
984 | #endif | ||
985 | |||
986 | /* Do the substitution. */ | ||
987 | write_lock_bh(&table->lock); | ||
988 | /* Check inside lock: is the old number correct? */ | ||
989 | if (num_counters != table->private->number) { | ||
990 | duprintf("num_counters != table->private->number (%u/%u)\n", | ||
991 | num_counters, table->private->number); | ||
992 | write_unlock_bh(&table->lock); | ||
993 | *error = -EAGAIN; | ||
994 | return NULL; | ||
995 | } | ||
996 | oldinfo = table->private; | ||
997 | table->private = newinfo; | ||
998 | newinfo->initial_entries = oldinfo->initial_entries; | ||
999 | write_unlock_bh(&table->lock); | ||
1000 | |||
1001 | return oldinfo; | ||
1002 | } | ||
1003 | |||
1004 | /* Gets counters. */ | 803 | /* Gets counters. */ |
1005 | static inline int | 804 | static inline int |
1006 | add_entry_to_counter(const struct ip6t_entry *e, | 805 | add_entry_to_counter(const struct ip6t_entry *e, |
1007 | struct ip6t_counters total[], | 806 | struct xt_counters total[], |
1008 | unsigned int *i) | 807 | unsigned int *i) |
1009 | { | 808 | { |
1010 | ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); | 809 | ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); |
@@ -1025,8 +824,8 @@ set_entry_to_counter(const struct ip6t_entry *e, | |||
1025 | } | 824 | } |
1026 | 825 | ||
1027 | static void | 826 | static void |
1028 | get_counters(const struct ip6t_table_info *t, | 827 | get_counters(const struct xt_table_info *t, |
1029 | struct ip6t_counters counters[]) | 828 | struct xt_counters counters[]) |
1030 | { | 829 | { |
1031 | unsigned int cpu; | 830 | unsigned int cpu; |
1032 | unsigned int i; | 831 | unsigned int i; |
@@ -1060,19 +859,20 @@ get_counters(const struct ip6t_table_info *t, | |||
1060 | 859 | ||
1061 | static int | 860 | static int |
1062 | copy_entries_to_user(unsigned int total_size, | 861 | copy_entries_to_user(unsigned int total_size, |
1063 | struct ip6t_table *table, | 862 | struct xt_table *table, |
1064 | void __user *userptr) | 863 | void __user *userptr) |
1065 | { | 864 | { |
1066 | unsigned int off, num, countersize; | 865 | unsigned int off, num, countersize; |
1067 | struct ip6t_entry *e; | 866 | struct ip6t_entry *e; |
1068 | struct ip6t_counters *counters; | 867 | struct xt_counters *counters; |
868 | struct xt_table_info *private = table->private; | ||
1069 | int ret = 0; | 869 | int ret = 0; |
1070 | void *loc_cpu_entry; | 870 | void *loc_cpu_entry; |
1071 | 871 | ||
1072 | /* We need atomic snapshot of counters: rest doesn't change | 872 | /* We need atomic snapshot of counters: rest doesn't change |
1073 | (other than comefrom, which userspace doesn't care | 873 | (other than comefrom, which userspace doesn't care |
1074 | about). */ | 874 | about). */ |
1075 | countersize = sizeof(struct ip6t_counters) * table->private->number; | 875 | countersize = sizeof(struct xt_counters) * private->number; |
1076 | counters = vmalloc(countersize); | 876 | counters = vmalloc(countersize); |
1077 | 877 | ||
1078 | if (counters == NULL) | 878 | if (counters == NULL) |
@@ -1080,11 +880,11 @@ copy_entries_to_user(unsigned int total_size, | |||
1080 | 880 | ||
1081 | /* First, sum counters... */ | 881 | /* First, sum counters... */ |
1082 | write_lock_bh(&table->lock); | 882 | write_lock_bh(&table->lock); |
1083 | get_counters(table->private, counters); | 883 | get_counters(private, counters); |
1084 | write_unlock_bh(&table->lock); | 884 | write_unlock_bh(&table->lock); |
1085 | 885 | ||
1086 | /* choose the copy that is on ourc node/cpu */ | 886 | /* choose the copy that is on ourc node/cpu */ |
1087 | loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; | 887 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
1088 | if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { | 888 | if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { |
1089 | ret = -EFAULT; | 889 | ret = -EFAULT; |
1090 | goto free_counters; | 890 | goto free_counters; |
@@ -1143,87 +943,42 @@ get_entries(const struct ip6t_get_entries *entries, | |||
1143 | struct ip6t_get_entries __user *uptr) | 943 | struct ip6t_get_entries __user *uptr) |
1144 | { | 944 | { |
1145 | int ret; | 945 | int ret; |
1146 | struct ip6t_table *t; | 946 | struct xt_table *t; |
1147 | 947 | ||
1148 | t = find_table_lock(entries->name); | 948 | t = xt_find_table_lock(AF_INET6, entries->name); |
1149 | if (t && !IS_ERR(t)) { | 949 | if (t && !IS_ERR(t)) { |
1150 | duprintf("t->private->number = %u\n", | 950 | struct xt_table_info *private = t->private; |
1151 | t->private->number); | 951 | duprintf("t->private->number = %u\n", private->number); |
1152 | if (entries->size == t->private->size) | 952 | if (entries->size == private->size) |
1153 | ret = copy_entries_to_user(t->private->size, | 953 | ret = copy_entries_to_user(private->size, |
1154 | t, uptr->entrytable); | 954 | t, uptr->entrytable); |
1155 | else { | 955 | else { |
1156 | duprintf("get_entries: I've got %u not %u!\n", | 956 | duprintf("get_entries: I've got %u not %u!\n", |
1157 | t->private->size, | 957 | private->size, entries->size); |
1158 | entries->size); | ||
1159 | ret = -EINVAL; | 958 | ret = -EINVAL; |
1160 | } | 959 | } |
1161 | module_put(t->me); | 960 | module_put(t->me); |
1162 | up(&ip6t_mutex); | 961 | xt_table_unlock(t); |
1163 | } else | 962 | } else |
1164 | ret = t ? PTR_ERR(t) : -ENOENT; | 963 | ret = t ? PTR_ERR(t) : -ENOENT; |
1165 | 964 | ||
1166 | return ret; | 965 | return ret; |
1167 | } | 966 | } |
1168 | 967 | ||
1169 | static void free_table_info(struct ip6t_table_info *info) | ||
1170 | { | ||
1171 | int cpu; | ||
1172 | for_each_cpu(cpu) { | ||
1173 | if (info->size <= PAGE_SIZE) | ||
1174 | kfree(info->entries[cpu]); | ||
1175 | else | ||
1176 | vfree(info->entries[cpu]); | ||
1177 | } | ||
1178 | kfree(info); | ||
1179 | } | ||
1180 | |||
1181 | static struct ip6t_table_info *alloc_table_info(unsigned int size) | ||
1182 | { | ||
1183 | struct ip6t_table_info *newinfo; | ||
1184 | int cpu; | ||
1185 | |||
1186 | newinfo = kzalloc(sizeof(struct ip6t_table_info), GFP_KERNEL); | ||
1187 | if (!newinfo) | ||
1188 | return NULL; | ||
1189 | |||
1190 | newinfo->size = size; | ||
1191 | |||
1192 | for_each_cpu(cpu) { | ||
1193 | if (size <= PAGE_SIZE) | ||
1194 | newinfo->entries[cpu] = kmalloc_node(size, | ||
1195 | GFP_KERNEL, | ||
1196 | cpu_to_node(cpu)); | ||
1197 | else | ||
1198 | newinfo->entries[cpu] = vmalloc_node(size, | ||
1199 | cpu_to_node(cpu)); | ||
1200 | if (newinfo->entries[cpu] == NULL) { | ||
1201 | free_table_info(newinfo); | ||
1202 | return NULL; | ||
1203 | } | ||
1204 | } | ||
1205 | |||
1206 | return newinfo; | ||
1207 | } | ||
1208 | |||
1209 | static int | 968 | static int |
1210 | do_replace(void __user *user, unsigned int len) | 969 | do_replace(void __user *user, unsigned int len) |
1211 | { | 970 | { |
1212 | int ret; | 971 | int ret; |
1213 | struct ip6t_replace tmp; | 972 | struct ip6t_replace tmp; |
1214 | struct ip6t_table *t; | 973 | struct xt_table *t; |
1215 | struct ip6t_table_info *newinfo, *oldinfo; | 974 | struct xt_table_info *newinfo, *oldinfo; |
1216 | struct ip6t_counters *counters; | 975 | struct xt_counters *counters; |
1217 | void *loc_cpu_entry, *loc_cpu_old_entry; | 976 | void *loc_cpu_entry, *loc_cpu_old_entry; |
1218 | 977 | ||
1219 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) | 978 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) |
1220 | return -EFAULT; | 979 | return -EFAULT; |
1221 | 980 | ||
1222 | /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ | 981 | newinfo = xt_alloc_table_info(tmp.size); |
1223 | if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages) | ||
1224 | return -ENOMEM; | ||
1225 | |||
1226 | newinfo = alloc_table_info(tmp.size); | ||
1227 | if (!newinfo) | 982 | if (!newinfo) |
1228 | return -ENOMEM; | 983 | return -ENOMEM; |
1229 | 984 | ||
@@ -1235,7 +990,7 @@ do_replace(void __user *user, unsigned int len) | |||
1235 | goto free_newinfo; | 990 | goto free_newinfo; |
1236 | } | 991 | } |
1237 | 992 | ||
1238 | counters = vmalloc(tmp.num_counters * sizeof(struct ip6t_counters)); | 993 | counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters)); |
1239 | if (!counters) { | 994 | if (!counters) { |
1240 | ret = -ENOMEM; | 995 | ret = -ENOMEM; |
1241 | goto free_newinfo; | 996 | goto free_newinfo; |
@@ -1249,7 +1004,7 @@ do_replace(void __user *user, unsigned int len) | |||
1249 | 1004 | ||
1250 | duprintf("ip_tables: Translated table\n"); | 1005 | duprintf("ip_tables: Translated table\n"); |
1251 | 1006 | ||
1252 | t = try_then_request_module(find_table_lock(tmp.name), | 1007 | t = try_then_request_module(xt_find_table_lock(AF_INET6, tmp.name), |
1253 | "ip6table_%s", tmp.name); | 1008 | "ip6table_%s", tmp.name); |
1254 | if (!t || IS_ERR(t)) { | 1009 | if (!t || IS_ERR(t)) { |
1255 | ret = t ? PTR_ERR(t) : -ENOENT; | 1010 | ret = t ? PTR_ERR(t) : -ENOENT; |
@@ -1264,7 +1019,7 @@ do_replace(void __user *user, unsigned int len) | |||
1264 | goto put_module; | 1019 | goto put_module; |
1265 | } | 1020 | } |
1266 | 1021 | ||
1267 | oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); | 1022 | oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret); |
1268 | if (!oldinfo) | 1023 | if (!oldinfo) |
1269 | goto put_module; | 1024 | goto put_module; |
1270 | 1025 | ||
@@ -1283,23 +1038,23 @@ do_replace(void __user *user, unsigned int len) | |||
1283 | /* Decrease module usage counts and free resource */ | 1038 | /* Decrease module usage counts and free resource */ |
1284 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; | 1039 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; |
1285 | IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); | 1040 | IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); |
1286 | free_table_info(oldinfo); | 1041 | xt_free_table_info(oldinfo); |
1287 | if (copy_to_user(tmp.counters, counters, | 1042 | if (copy_to_user(tmp.counters, counters, |
1288 | sizeof(struct ip6t_counters) * tmp.num_counters) != 0) | 1043 | sizeof(struct xt_counters) * tmp.num_counters) != 0) |
1289 | ret = -EFAULT; | 1044 | ret = -EFAULT; |
1290 | vfree(counters); | 1045 | vfree(counters); |
1291 | up(&ip6t_mutex); | 1046 | xt_table_unlock(t); |
1292 | return ret; | 1047 | return ret; |
1293 | 1048 | ||
1294 | put_module: | 1049 | put_module: |
1295 | module_put(t->me); | 1050 | module_put(t->me); |
1296 | up(&ip6t_mutex); | 1051 | xt_table_unlock(t); |
1297 | free_newinfo_counters_untrans: | 1052 | free_newinfo_counters_untrans: |
1298 | IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); | 1053 | IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); |
1299 | free_newinfo_counters: | 1054 | free_newinfo_counters: |
1300 | vfree(counters); | 1055 | vfree(counters); |
1301 | free_newinfo: | 1056 | free_newinfo: |
1302 | free_table_info(newinfo); | 1057 | xt_free_table_info(newinfo); |
1303 | return ret; | 1058 | return ret; |
1304 | } | 1059 | } |
1305 | 1060 | ||
@@ -1307,7 +1062,7 @@ do_replace(void __user *user, unsigned int len) | |||
1307 | * and everything is OK. */ | 1062 | * and everything is OK. */ |
1308 | static inline int | 1063 | static inline int |
1309 | add_counter_to_entry(struct ip6t_entry *e, | 1064 | add_counter_to_entry(struct ip6t_entry *e, |
1310 | const struct ip6t_counters addme[], | 1065 | const struct xt_counters addme[], |
1311 | unsigned int *i) | 1066 | unsigned int *i) |
1312 | { | 1067 | { |
1313 | #if 0 | 1068 | #if 0 |
@@ -1329,15 +1084,16 @@ static int | |||
1329 | do_add_counters(void __user *user, unsigned int len) | 1084 | do_add_counters(void __user *user, unsigned int len) |
1330 | { | 1085 | { |
1331 | unsigned int i; | 1086 | unsigned int i; |
1332 | struct ip6t_counters_info tmp, *paddc; | 1087 | struct xt_counters_info tmp, *paddc; |
1333 | struct ip6t_table *t; | 1088 | struct xt_table_info *private; |
1089 | struct xt_table *t; | ||
1334 | int ret = 0; | 1090 | int ret = 0; |
1335 | void *loc_cpu_entry; | 1091 | void *loc_cpu_entry; |
1336 | 1092 | ||
1337 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) | 1093 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) |
1338 | return -EFAULT; | 1094 | return -EFAULT; |
1339 | 1095 | ||
1340 | if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ip6t_counters)) | 1096 | if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters)) |
1341 | return -EINVAL; | 1097 | return -EINVAL; |
1342 | 1098 | ||
1343 | paddc = vmalloc(len); | 1099 | paddc = vmalloc(len); |
@@ -1349,29 +1105,30 @@ do_add_counters(void __user *user, unsigned int len) | |||
1349 | goto free; | 1105 | goto free; |
1350 | } | 1106 | } |
1351 | 1107 | ||
1352 | t = find_table_lock(tmp.name); | 1108 | t = xt_find_table_lock(AF_INET6, tmp.name); |
1353 | if (!t || IS_ERR(t)) { | 1109 | if (!t || IS_ERR(t)) { |
1354 | ret = t ? PTR_ERR(t) : -ENOENT; | 1110 | ret = t ? PTR_ERR(t) : -ENOENT; |
1355 | goto free; | 1111 | goto free; |
1356 | } | 1112 | } |
1357 | 1113 | ||
1358 | write_lock_bh(&t->lock); | 1114 | write_lock_bh(&t->lock); |
1359 | if (t->private->number != paddc->num_counters) { | 1115 | private = t->private; |
1116 | if (private->number != paddc->num_counters) { | ||
1360 | ret = -EINVAL; | 1117 | ret = -EINVAL; |
1361 | goto unlock_up_free; | 1118 | goto unlock_up_free; |
1362 | } | 1119 | } |
1363 | 1120 | ||
1364 | i = 0; | 1121 | i = 0; |
1365 | /* Choose the copy that is on our node */ | 1122 | /* Choose the copy that is on our node */ |
1366 | loc_cpu_entry = t->private->entries[smp_processor_id()]; | 1123 | loc_cpu_entry = private->entries[smp_processor_id()]; |
1367 | IP6T_ENTRY_ITERATE(loc_cpu_entry, | 1124 | IP6T_ENTRY_ITERATE(loc_cpu_entry, |
1368 | t->private->size, | 1125 | private->size, |
1369 | add_counter_to_entry, | 1126 | add_counter_to_entry, |
1370 | paddc->counters, | 1127 | paddc->counters, |
1371 | &i); | 1128 | &i); |
1372 | unlock_up_free: | 1129 | unlock_up_free: |
1373 | write_unlock_bh(&t->lock); | 1130 | write_unlock_bh(&t->lock); |
1374 | up(&ip6t_mutex); | 1131 | xt_table_unlock(t); |
1375 | module_put(t->me); | 1132 | module_put(t->me); |
1376 | free: | 1133 | free: |
1377 | vfree(paddc); | 1134 | vfree(paddc); |
@@ -1415,7 +1172,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1415 | switch (cmd) { | 1172 | switch (cmd) { |
1416 | case IP6T_SO_GET_INFO: { | 1173 | case IP6T_SO_GET_INFO: { |
1417 | char name[IP6T_TABLE_MAXNAMELEN]; | 1174 | char name[IP6T_TABLE_MAXNAMELEN]; |
1418 | struct ip6t_table *t; | 1175 | struct xt_table *t; |
1419 | 1176 | ||
1420 | if (*len != sizeof(struct ip6t_getinfo)) { | 1177 | if (*len != sizeof(struct ip6t_getinfo)) { |
1421 | duprintf("length %u != %u\n", *len, | 1178 | duprintf("length %u != %u\n", *len, |
@@ -1430,25 +1187,26 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1430 | } | 1187 | } |
1431 | name[IP6T_TABLE_MAXNAMELEN-1] = '\0'; | 1188 | name[IP6T_TABLE_MAXNAMELEN-1] = '\0'; |
1432 | 1189 | ||
1433 | t = try_then_request_module(find_table_lock(name), | 1190 | t = try_then_request_module(xt_find_table_lock(AF_INET6, name), |
1434 | "ip6table_%s", name); | 1191 | "ip6table_%s", name); |
1435 | if (t && !IS_ERR(t)) { | 1192 | if (t && !IS_ERR(t)) { |
1436 | struct ip6t_getinfo info; | 1193 | struct ip6t_getinfo info; |
1194 | struct xt_table_info *private = t->private; | ||
1437 | 1195 | ||
1438 | info.valid_hooks = t->valid_hooks; | 1196 | info.valid_hooks = t->valid_hooks; |
1439 | memcpy(info.hook_entry, t->private->hook_entry, | 1197 | memcpy(info.hook_entry, private->hook_entry, |
1440 | sizeof(info.hook_entry)); | 1198 | sizeof(info.hook_entry)); |
1441 | memcpy(info.underflow, t->private->underflow, | 1199 | memcpy(info.underflow, private->underflow, |
1442 | sizeof(info.underflow)); | 1200 | sizeof(info.underflow)); |
1443 | info.num_entries = t->private->number; | 1201 | info.num_entries = private->number; |
1444 | info.size = t->private->size; | 1202 | info.size = private->size; |
1445 | memcpy(info.name, name, sizeof(info.name)); | 1203 | memcpy(info.name, name, sizeof(info.name)); |
1446 | 1204 | ||
1447 | if (copy_to_user(user, &info, *len) != 0) | 1205 | if (copy_to_user(user, &info, *len) != 0) |
1448 | ret = -EFAULT; | 1206 | ret = -EFAULT; |
1449 | else | 1207 | else |
1450 | ret = 0; | 1208 | ret = 0; |
1451 | up(&ip6t_mutex); | 1209 | xt_table_unlock(t); |
1452 | module_put(t->me); | 1210 | module_put(t->me); |
1453 | } else | 1211 | } else |
1454 | ret = t ? PTR_ERR(t) : -ENOENT; | 1212 | ret = t ? PTR_ERR(t) : -ENOENT; |
@@ -1475,7 +1233,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1475 | case IP6T_SO_GET_REVISION_MATCH: | 1233 | case IP6T_SO_GET_REVISION_MATCH: |
1476 | case IP6T_SO_GET_REVISION_TARGET: { | 1234 | case IP6T_SO_GET_REVISION_TARGET: { |
1477 | struct ip6t_get_revision rev; | 1235 | struct ip6t_get_revision rev; |
1478 | int (*revfn)(const char *, u8, int *); | 1236 | int target; |
1479 | 1237 | ||
1480 | if (*len != sizeof(rev)) { | 1238 | if (*len != sizeof(rev)) { |
1481 | ret = -EINVAL; | 1239 | ret = -EINVAL; |
@@ -1487,12 +1245,13 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1487 | } | 1245 | } |
1488 | 1246 | ||
1489 | if (cmd == IP6T_SO_GET_REVISION_TARGET) | 1247 | if (cmd == IP6T_SO_GET_REVISION_TARGET) |
1490 | revfn = target_revfn; | 1248 | target = 1; |
1491 | else | 1249 | else |
1492 | revfn = match_revfn; | 1250 | target = 0; |
1493 | 1251 | ||
1494 | try_then_request_module(find_revision(rev.name, rev.revision, | 1252 | try_then_request_module(xt_find_revision(AF_INET6, rev.name, |
1495 | revfn, &ret), | 1253 | rev.revision, |
1254 | target, &ret), | ||
1496 | "ip6t_%s", rev.name); | 1255 | "ip6t_%s", rev.name); |
1497 | break; | 1256 | break; |
1498 | } | 1257 | } |
@@ -1505,61 +1264,16 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1505 | return ret; | 1264 | return ret; |
1506 | } | 1265 | } |
1507 | 1266 | ||
1508 | /* Registration hooks for targets. */ | 1267 | int ip6t_register_table(struct xt_table *table, |
1509 | int | ||
1510 | ip6t_register_target(struct ip6t_target *target) | ||
1511 | { | ||
1512 | int ret; | ||
1513 | |||
1514 | ret = down_interruptible(&ip6t_mutex); | ||
1515 | if (ret != 0) | ||
1516 | return ret; | ||
1517 | list_add(&target->list, &ip6t_target); | ||
1518 | up(&ip6t_mutex); | ||
1519 | return ret; | ||
1520 | } | ||
1521 | |||
1522 | void | ||
1523 | ip6t_unregister_target(struct ip6t_target *target) | ||
1524 | { | ||
1525 | down(&ip6t_mutex); | ||
1526 | LIST_DELETE(&ip6t_target, target); | ||
1527 | up(&ip6t_mutex); | ||
1528 | } | ||
1529 | |||
1530 | int | ||
1531 | ip6t_register_match(struct ip6t_match *match) | ||
1532 | { | ||
1533 | int ret; | ||
1534 | |||
1535 | ret = down_interruptible(&ip6t_mutex); | ||
1536 | if (ret != 0) | ||
1537 | return ret; | ||
1538 | |||
1539 | list_add(&match->list, &ip6t_match); | ||
1540 | up(&ip6t_mutex); | ||
1541 | |||
1542 | return ret; | ||
1543 | } | ||
1544 | |||
1545 | void | ||
1546 | ip6t_unregister_match(struct ip6t_match *match) | ||
1547 | { | ||
1548 | down(&ip6t_mutex); | ||
1549 | LIST_DELETE(&ip6t_match, match); | ||
1550 | up(&ip6t_mutex); | ||
1551 | } | ||
1552 | |||
1553 | int ip6t_register_table(struct ip6t_table *table, | ||
1554 | const struct ip6t_replace *repl) | 1268 | const struct ip6t_replace *repl) |
1555 | { | 1269 | { |
1556 | int ret; | 1270 | int ret; |
1557 | struct ip6t_table_info *newinfo; | 1271 | struct xt_table_info *newinfo; |
1558 | static struct ip6t_table_info bootstrap | 1272 | static struct xt_table_info bootstrap |
1559 | = { 0, 0, 0, { 0 }, { 0 }, { } }; | 1273 | = { 0, 0, 0, { 0 }, { 0 }, { } }; |
1560 | void *loc_cpu_entry; | 1274 | void *loc_cpu_entry; |
1561 | 1275 | ||
1562 | newinfo = alloc_table_info(repl->size); | 1276 | newinfo = xt_alloc_table_info(repl->size); |
1563 | if (!newinfo) | 1277 | if (!newinfo) |
1564 | return -ENOMEM; | 1278 | return -ENOMEM; |
1565 | 1279 | ||
@@ -1573,244 +1287,29 @@ int ip6t_register_table(struct ip6t_table *table, | |||
1573 | repl->hook_entry, | 1287 | repl->hook_entry, |
1574 | repl->underflow); | 1288 | repl->underflow); |
1575 | if (ret != 0) { | 1289 | if (ret != 0) { |
1576 | free_table_info(newinfo); | 1290 | xt_free_table_info(newinfo); |
1577 | return ret; | 1291 | return ret; |
1578 | } | 1292 | } |
1579 | 1293 | ||
1580 | ret = down_interruptible(&ip6t_mutex); | 1294 | if (xt_register_table(table, &bootstrap, newinfo) != 0) { |
1581 | if (ret != 0) { | 1295 | xt_free_table_info(newinfo); |
1582 | free_table_info(newinfo); | ||
1583 | return ret; | 1296 | return ret; |
1584 | } | 1297 | } |
1585 | 1298 | ||
1586 | /* Don't autoload: we'd eat our tail... */ | 1299 | return 0; |
1587 | if (list_named_find(&ip6t_tables, table->name)) { | ||
1588 | ret = -EEXIST; | ||
1589 | goto free_unlock; | ||
1590 | } | ||
1591 | |||
1592 | /* Simplifies replace_table code. */ | ||
1593 | table->private = &bootstrap; | ||
1594 | if (!replace_table(table, 0, newinfo, &ret)) | ||
1595 | goto free_unlock; | ||
1596 | |||
1597 | duprintf("table->private->number = %u\n", | ||
1598 | table->private->number); | ||
1599 | |||
1600 | /* save number of initial entries */ | ||
1601 | table->private->initial_entries = table->private->number; | ||
1602 | |||
1603 | rwlock_init(&table->lock); | ||
1604 | list_prepend(&ip6t_tables, table); | ||
1605 | |||
1606 | unlock: | ||
1607 | up(&ip6t_mutex); | ||
1608 | return ret; | ||
1609 | |||
1610 | free_unlock: | ||
1611 | free_table_info(newinfo); | ||
1612 | goto unlock; | ||
1613 | } | 1300 | } |
1614 | 1301 | ||
1615 | void ip6t_unregister_table(struct ip6t_table *table) | 1302 | void ip6t_unregister_table(struct xt_table *table) |
1616 | { | 1303 | { |
1304 | struct xt_table_info *private; | ||
1617 | void *loc_cpu_entry; | 1305 | void *loc_cpu_entry; |
1618 | 1306 | ||
1619 | down(&ip6t_mutex); | 1307 | private = xt_unregister_table(table); |
1620 | LIST_DELETE(&ip6t_tables, table); | ||
1621 | up(&ip6t_mutex); | ||
1622 | 1308 | ||
1623 | /* Decrease module usage counts and free resources */ | 1309 | /* Decrease module usage counts and free resources */ |
1624 | loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; | 1310 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
1625 | IP6T_ENTRY_ITERATE(loc_cpu_entry, table->private->size, | 1311 | IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); |
1626 | cleanup_entry, NULL); | 1312 | xt_free_table_info(private); |
1627 | free_table_info(table->private); | ||
1628 | } | ||
1629 | |||
1630 | /* Returns 1 if the port is matched by the range, 0 otherwise */ | ||
1631 | static inline int | ||
1632 | port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert) | ||
1633 | { | ||
1634 | int ret; | ||
1635 | |||
1636 | ret = (port >= min && port <= max) ^ invert; | ||
1637 | return ret; | ||
1638 | } | ||
1639 | |||
1640 | static int | ||
1641 | tcp_find_option(u_int8_t option, | ||
1642 | const struct sk_buff *skb, | ||
1643 | unsigned int tcpoff, | ||
1644 | unsigned int optlen, | ||
1645 | int invert, | ||
1646 | int *hotdrop) | ||
1647 | { | ||
1648 | /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ | ||
1649 | u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; | ||
1650 | unsigned int i; | ||
1651 | |||
1652 | duprintf("tcp_match: finding option\n"); | ||
1653 | if (!optlen) | ||
1654 | return invert; | ||
1655 | /* If we don't have the whole header, drop packet. */ | ||
1656 | op = skb_header_pointer(skb, tcpoff + sizeof(struct tcphdr), optlen, | ||
1657 | _opt); | ||
1658 | if (op == NULL) { | ||
1659 | *hotdrop = 1; | ||
1660 | return 0; | ||
1661 | } | ||
1662 | |||
1663 | for (i = 0; i < optlen; ) { | ||
1664 | if (op[i] == option) return !invert; | ||
1665 | if (op[i] < 2) i++; | ||
1666 | else i += op[i+1]?:1; | ||
1667 | } | ||
1668 | |||
1669 | return invert; | ||
1670 | } | ||
1671 | |||
1672 | static int | ||
1673 | tcp_match(const struct sk_buff *skb, | ||
1674 | const struct net_device *in, | ||
1675 | const struct net_device *out, | ||
1676 | const void *matchinfo, | ||
1677 | int offset, | ||
1678 | unsigned int protoff, | ||
1679 | int *hotdrop) | ||
1680 | { | ||
1681 | struct tcphdr _tcph, *th; | ||
1682 | const struct ip6t_tcp *tcpinfo = matchinfo; | ||
1683 | |||
1684 | if (offset) { | ||
1685 | /* To quote Alan: | ||
1686 | |||
1687 | Don't allow a fragment of TCP 8 bytes in. Nobody normal | ||
1688 | causes this. Its a cracker trying to break in by doing a | ||
1689 | flag overwrite to pass the direction checks. | ||
1690 | */ | ||
1691 | if (offset == 1) { | ||
1692 | duprintf("Dropping evil TCP offset=1 frag.\n"); | ||
1693 | *hotdrop = 1; | ||
1694 | } | ||
1695 | /* Must not be a fragment. */ | ||
1696 | return 0; | ||
1697 | } | ||
1698 | |||
1699 | #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) | ||
1700 | |||
1701 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); | ||
1702 | if (th == NULL) { | ||
1703 | /* We've been asked to examine this packet, and we | ||
1704 | can't. Hence, no choice but to drop. */ | ||
1705 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); | ||
1706 | *hotdrop = 1; | ||
1707 | return 0; | ||
1708 | } | ||
1709 | |||
1710 | if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], | ||
1711 | ntohs(th->source), | ||
1712 | !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT))) | ||
1713 | return 0; | ||
1714 | if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], | ||
1715 | ntohs(th->dest), | ||
1716 | !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT))) | ||
1717 | return 0; | ||
1718 | if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) | ||
1719 | == tcpinfo->flg_cmp, | ||
1720 | IP6T_TCP_INV_FLAGS)) | ||
1721 | return 0; | ||
1722 | if (tcpinfo->option) { | ||
1723 | if (th->doff * 4 < sizeof(_tcph)) { | ||
1724 | *hotdrop = 1; | ||
1725 | return 0; | ||
1726 | } | ||
1727 | if (!tcp_find_option(tcpinfo->option, skb, protoff, | ||
1728 | th->doff*4 - sizeof(*th), | ||
1729 | tcpinfo->invflags & IP6T_TCP_INV_OPTION, | ||
1730 | hotdrop)) | ||
1731 | return 0; | ||
1732 | } | ||
1733 | return 1; | ||
1734 | } | ||
1735 | |||
1736 | /* Called when user tries to insert an entry of this type. */ | ||
1737 | static int | ||
1738 | tcp_checkentry(const char *tablename, | ||
1739 | const struct ip6t_ip6 *ipv6, | ||
1740 | void *matchinfo, | ||
1741 | unsigned int matchsize, | ||
1742 | unsigned int hook_mask) | ||
1743 | { | ||
1744 | const struct ip6t_tcp *tcpinfo = matchinfo; | ||
1745 | |||
1746 | /* Must specify proto == TCP, and no unknown invflags */ | ||
1747 | return ipv6->proto == IPPROTO_TCP | ||
1748 | && !(ipv6->invflags & IP6T_INV_PROTO) | ||
1749 | && matchsize == IP6T_ALIGN(sizeof(struct ip6t_tcp)) | ||
1750 | && !(tcpinfo->invflags & ~IP6T_TCP_INV_MASK); | ||
1751 | } | ||
1752 | |||
1753 | static int | ||
1754 | udp_match(const struct sk_buff *skb, | ||
1755 | const struct net_device *in, | ||
1756 | const struct net_device *out, | ||
1757 | const void *matchinfo, | ||
1758 | int offset, | ||
1759 | unsigned int protoff, | ||
1760 | int *hotdrop) | ||
1761 | { | ||
1762 | struct udphdr _udph, *uh; | ||
1763 | const struct ip6t_udp *udpinfo = matchinfo; | ||
1764 | |||
1765 | /* Must not be a fragment. */ | ||
1766 | if (offset) | ||
1767 | return 0; | ||
1768 | |||
1769 | uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph); | ||
1770 | if (uh == NULL) { | ||
1771 | /* We've been asked to examine this packet, and we | ||
1772 | can't. Hence, no choice but to drop. */ | ||
1773 | duprintf("Dropping evil UDP tinygram.\n"); | ||
1774 | *hotdrop = 1; | ||
1775 | return 0; | ||
1776 | } | ||
1777 | |||
1778 | return port_match(udpinfo->spts[0], udpinfo->spts[1], | ||
1779 | ntohs(uh->source), | ||
1780 | !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT)) | ||
1781 | && port_match(udpinfo->dpts[0], udpinfo->dpts[1], | ||
1782 | ntohs(uh->dest), | ||
1783 | !!(udpinfo->invflags & IP6T_UDP_INV_DSTPT)); | ||
1784 | } | ||
1785 | |||
1786 | /* Called when user tries to insert an entry of this type. */ | ||
1787 | static int | ||
1788 | udp_checkentry(const char *tablename, | ||
1789 | const struct ip6t_ip6 *ipv6, | ||
1790 | void *matchinfo, | ||
1791 | unsigned int matchinfosize, | ||
1792 | unsigned int hook_mask) | ||
1793 | { | ||
1794 | const struct ip6t_udp *udpinfo = matchinfo; | ||
1795 | |||
1796 | /* Must specify proto == UDP, and no unknown invflags */ | ||
1797 | if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & IP6T_INV_PROTO)) { | ||
1798 | duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto, | ||
1799 | IPPROTO_UDP); | ||
1800 | return 0; | ||
1801 | } | ||
1802 | if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_udp))) { | ||
1803 | duprintf("ip6t_udp: matchsize %u != %u\n", | ||
1804 | matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_udp))); | ||
1805 | return 0; | ||
1806 | } | ||
1807 | if (udpinfo->invflags & ~IP6T_UDP_INV_MASK) { | ||
1808 | duprintf("ip6t_udp: unknown flags %X\n", | ||
1809 | udpinfo->invflags); | ||
1810 | return 0; | ||
1811 | } | ||
1812 | |||
1813 | return 1; | ||
1814 | } | 1313 | } |
1815 | 1314 | ||
1816 | /* Returns 1 if the type and code is matched by the range, 0 otherwise */ | 1315 | /* Returns 1 if the type and code is matched by the range, 0 otherwise */ |
@@ -1858,11 +1357,12 @@ icmp6_match(const struct sk_buff *skb, | |||
1858 | /* Called when user tries to insert an entry of this type. */ | 1357 | /* Called when user tries to insert an entry of this type. */ |
1859 | static int | 1358 | static int |
1860 | icmp6_checkentry(const char *tablename, | 1359 | icmp6_checkentry(const char *tablename, |
1861 | const struct ip6t_ip6 *ipv6, | 1360 | const void *entry, |
1862 | void *matchinfo, | 1361 | void *matchinfo, |
1863 | unsigned int matchsize, | 1362 | unsigned int matchsize, |
1864 | unsigned int hook_mask) | 1363 | unsigned int hook_mask) |
1865 | { | 1364 | { |
1365 | const struct ip6t_ip6 *ipv6 = entry; | ||
1866 | const struct ip6t_icmp *icmpinfo = matchinfo; | 1366 | const struct ip6t_icmp *icmpinfo = matchinfo; |
1867 | 1367 | ||
1868 | /* Must specify proto == ICMP, and no unknown invflags */ | 1368 | /* Must specify proto == ICMP, and no unknown invflags */ |
@@ -1892,164 +1392,42 @@ static struct nf_sockopt_ops ip6t_sockopts = { | |||
1892 | .get = do_ip6t_get_ctl, | 1392 | .get = do_ip6t_get_ctl, |
1893 | }; | 1393 | }; |
1894 | 1394 | ||
1895 | static struct ip6t_match tcp_matchstruct = { | ||
1896 | .name = "tcp", | ||
1897 | .match = &tcp_match, | ||
1898 | .checkentry = &tcp_checkentry, | ||
1899 | }; | ||
1900 | |||
1901 | static struct ip6t_match udp_matchstruct = { | ||
1902 | .name = "udp", | ||
1903 | .match = &udp_match, | ||
1904 | .checkentry = &udp_checkentry, | ||
1905 | }; | ||
1906 | |||
1907 | static struct ip6t_match icmp6_matchstruct = { | 1395 | static struct ip6t_match icmp6_matchstruct = { |
1908 | .name = "icmp6", | 1396 | .name = "icmp6", |
1909 | .match = &icmp6_match, | 1397 | .match = &icmp6_match, |
1910 | .checkentry = &icmp6_checkentry, | 1398 | .checkentry = &icmp6_checkentry, |
1911 | }; | 1399 | }; |
1912 | 1400 | ||
1913 | #ifdef CONFIG_PROC_FS | ||
1914 | static inline int print_name(const char *i, | ||
1915 | off_t start_offset, char *buffer, int length, | ||
1916 | off_t *pos, unsigned int *count) | ||
1917 | { | ||
1918 | if ((*count)++ >= start_offset) { | ||
1919 | unsigned int namelen; | ||
1920 | |||
1921 | namelen = sprintf(buffer + *pos, "%s\n", | ||
1922 | i + sizeof(struct list_head)); | ||
1923 | if (*pos + namelen > length) { | ||
1924 | /* Stop iterating */ | ||
1925 | return 1; | ||
1926 | } | ||
1927 | *pos += namelen; | ||
1928 | } | ||
1929 | return 0; | ||
1930 | } | ||
1931 | |||
1932 | static inline int print_target(const struct ip6t_target *t, | ||
1933 | off_t start_offset, char *buffer, int length, | ||
1934 | off_t *pos, unsigned int *count) | ||
1935 | { | ||
1936 | if (t == &ip6t_standard_target || t == &ip6t_error_target) | ||
1937 | return 0; | ||
1938 | return print_name((char *)t, start_offset, buffer, length, pos, count); | ||
1939 | } | ||
1940 | |||
1941 | static int ip6t_get_tables(char *buffer, char **start, off_t offset, int length) | ||
1942 | { | ||
1943 | off_t pos = 0; | ||
1944 | unsigned int count = 0; | ||
1945 | |||
1946 | if (down_interruptible(&ip6t_mutex) != 0) | ||
1947 | return 0; | ||
1948 | |||
1949 | LIST_FIND(&ip6t_tables, print_name, char *, | ||
1950 | offset, buffer, length, &pos, &count); | ||
1951 | |||
1952 | up(&ip6t_mutex); | ||
1953 | |||
1954 | /* `start' hack - see fs/proc/generic.c line ~105 */ | ||
1955 | *start=(char *)((unsigned long)count-offset); | ||
1956 | return pos; | ||
1957 | } | ||
1958 | |||
1959 | static int ip6t_get_targets(char *buffer, char **start, off_t offset, int length) | ||
1960 | { | ||
1961 | off_t pos = 0; | ||
1962 | unsigned int count = 0; | ||
1963 | |||
1964 | if (down_interruptible(&ip6t_mutex) != 0) | ||
1965 | return 0; | ||
1966 | |||
1967 | LIST_FIND(&ip6t_target, print_target, struct ip6t_target *, | ||
1968 | offset, buffer, length, &pos, &count); | ||
1969 | |||
1970 | up(&ip6t_mutex); | ||
1971 | |||
1972 | *start = (char *)((unsigned long)count - offset); | ||
1973 | return pos; | ||
1974 | } | ||
1975 | |||
1976 | static int ip6t_get_matches(char *buffer, char **start, off_t offset, int length) | ||
1977 | { | ||
1978 | off_t pos = 0; | ||
1979 | unsigned int count = 0; | ||
1980 | |||
1981 | if (down_interruptible(&ip6t_mutex) != 0) | ||
1982 | return 0; | ||
1983 | |||
1984 | LIST_FIND(&ip6t_match, print_name, char *, | ||
1985 | offset, buffer, length, &pos, &count); | ||
1986 | |||
1987 | up(&ip6t_mutex); | ||
1988 | |||
1989 | *start = (char *)((unsigned long)count - offset); | ||
1990 | return pos; | ||
1991 | } | ||
1992 | |||
1993 | static const struct { char *name; get_info_t *get_info; } ip6t_proc_entry[] = | ||
1994 | { { "ip6_tables_names", ip6t_get_tables }, | ||
1995 | { "ip6_tables_targets", ip6t_get_targets }, | ||
1996 | { "ip6_tables_matches", ip6t_get_matches }, | ||
1997 | { NULL, NULL} }; | ||
1998 | #endif /*CONFIG_PROC_FS*/ | ||
1999 | |||
2000 | static int __init init(void) | 1401 | static int __init init(void) |
2001 | { | 1402 | { |
2002 | int ret; | 1403 | int ret; |
2003 | 1404 | ||
1405 | xt_proto_init(AF_INET6); | ||
1406 | |||
2004 | /* Noone else will be downing sem now, so we won't sleep */ | 1407 | /* Noone else will be downing sem now, so we won't sleep */ |
2005 | down(&ip6t_mutex); | 1408 | xt_register_target(AF_INET6, &ip6t_standard_target); |
2006 | list_append(&ip6t_target, &ip6t_standard_target); | 1409 | xt_register_target(AF_INET6, &ip6t_error_target); |
2007 | list_append(&ip6t_target, &ip6t_error_target); | 1410 | xt_register_match(AF_INET6, &icmp6_matchstruct); |
2008 | list_append(&ip6t_match, &tcp_matchstruct); | ||
2009 | list_append(&ip6t_match, &udp_matchstruct); | ||
2010 | list_append(&ip6t_match, &icmp6_matchstruct); | ||
2011 | up(&ip6t_mutex); | ||
2012 | 1411 | ||
2013 | /* Register setsockopt */ | 1412 | /* Register setsockopt */ |
2014 | ret = nf_register_sockopt(&ip6t_sockopts); | 1413 | ret = nf_register_sockopt(&ip6t_sockopts); |
2015 | if (ret < 0) { | 1414 | if (ret < 0) { |
2016 | duprintf("Unable to register sockopts.\n"); | 1415 | duprintf("Unable to register sockopts.\n"); |
1416 | xt_proto_fini(AF_INET6); | ||
2017 | return ret; | 1417 | return ret; |
2018 | } | 1418 | } |
2019 | 1419 | ||
2020 | #ifdef CONFIG_PROC_FS | 1420 | printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); |
2021 | { | ||
2022 | struct proc_dir_entry *proc; | ||
2023 | int i; | ||
2024 | |||
2025 | for (i = 0; ip6t_proc_entry[i].name; i++) { | ||
2026 | proc = proc_net_create(ip6t_proc_entry[i].name, 0, | ||
2027 | ip6t_proc_entry[i].get_info); | ||
2028 | if (!proc) { | ||
2029 | while (--i >= 0) | ||
2030 | proc_net_remove(ip6t_proc_entry[i].name); | ||
2031 | nf_unregister_sockopt(&ip6t_sockopts); | ||
2032 | return -ENOMEM; | ||
2033 | } | ||
2034 | proc->owner = THIS_MODULE; | ||
2035 | } | ||
2036 | } | ||
2037 | #endif | ||
2038 | |||
2039 | printk("ip6_tables: (C) 2000-2002 Netfilter core team\n"); | ||
2040 | return 0; | 1421 | return 0; |
2041 | } | 1422 | } |
2042 | 1423 | ||
2043 | static void __exit fini(void) | 1424 | static void __exit fini(void) |
2044 | { | 1425 | { |
2045 | nf_unregister_sockopt(&ip6t_sockopts); | 1426 | nf_unregister_sockopt(&ip6t_sockopts); |
2046 | #ifdef CONFIG_PROC_FS | 1427 | xt_unregister_match(AF_INET6, &icmp6_matchstruct); |
2047 | { | 1428 | xt_unregister_target(AF_INET6, &ip6t_error_target); |
2048 | int i; | 1429 | xt_unregister_target(AF_INET6, &ip6t_standard_target); |
2049 | for (i = 0; ip6t_proc_entry[i].name; i++) | 1430 | xt_proto_fini(AF_INET6); |
2050 | proc_net_remove(ip6t_proc_entry[i].name); | ||
2051 | } | ||
2052 | #endif | ||
2053 | } | 1431 | } |
2054 | 1432 | ||
2055 | /* | 1433 | /* |
@@ -2128,10 +1506,6 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, | |||
2128 | EXPORT_SYMBOL(ip6t_register_table); | 1506 | EXPORT_SYMBOL(ip6t_register_table); |
2129 | EXPORT_SYMBOL(ip6t_unregister_table); | 1507 | EXPORT_SYMBOL(ip6t_unregister_table); |
2130 | EXPORT_SYMBOL(ip6t_do_table); | 1508 | EXPORT_SYMBOL(ip6t_do_table); |
2131 | EXPORT_SYMBOL(ip6t_register_match); | ||
2132 | EXPORT_SYMBOL(ip6t_unregister_match); | ||
2133 | EXPORT_SYMBOL(ip6t_register_target); | ||
2134 | EXPORT_SYMBOL(ip6t_unregister_target); | ||
2135 | EXPORT_SYMBOL(ip6t_ext_hdr); | 1509 | EXPORT_SYMBOL(ip6t_ext_hdr); |
2136 | EXPORT_SYMBOL(ipv6_find_hdr); | 1510 | EXPORT_SYMBOL(ipv6_find_hdr); |
2137 | EXPORT_SYMBOL(ip6_masked_addrcmp); | 1511 | EXPORT_SYMBOL(ip6_masked_addrcmp); |
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c index 8f5549b72720..306200c35057 100644 --- a/net/ipv6/netfilter/ip6t_HL.c +++ b/net/ipv6/netfilter/ip6t_HL.c | |||
@@ -62,7 +62,7 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb, | |||
62 | } | 62 | } |
63 | 63 | ||
64 | static int ip6t_hl_checkentry(const char *tablename, | 64 | static int ip6t_hl_checkentry(const char *tablename, |
65 | const struct ip6t_entry *e, | 65 | const void *entry, |
66 | void *targinfo, | 66 | void *targinfo, |
67 | unsigned int targinfosize, | 67 | unsigned int targinfosize, |
68 | unsigned int hook_mask) | 68 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index ae4653bfd654..77c725832dec 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -63,9 +63,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
63 | return; | 63 | return; |
64 | } | 64 | } |
65 | 65 | ||
66 | /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000" */ | 66 | /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */ |
67 | printk("SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->saddr)); | 67 | printk("SRC=" NIP6_FMT " DST=" NIP6_FMT " ", NIP6(ih->saddr), NIP6(ih->daddr)); |
68 | printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->daddr)); | ||
69 | 68 | ||
70 | /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ | 69 | /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ |
71 | printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", | 70 | printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", |
@@ -444,7 +443,7 @@ ip6t_log_target(struct sk_buff **pskb, | |||
444 | 443 | ||
445 | 444 | ||
446 | static int ip6t_log_checkentry(const char *tablename, | 445 | static int ip6t_log_checkentry(const char *tablename, |
447 | const struct ip6t_entry *e, | 446 | const void *entry, |
448 | void *targinfo, | 447 | void *targinfo, |
449 | unsigned int targinfosize, | 448 | unsigned int targinfosize, |
450 | unsigned int hook_mask) | 449 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c deleted file mode 100644 index eab8fb864ee0..000000000000 --- a/net/ipv6/netfilter/ip6t_MARK.c +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | /* This is a module which is used for setting the NFMARK field of an skb. */ | ||
2 | |||
3 | /* (C) 1999-2001 Marc Boucher <marc@mbsi.ca> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/skbuff.h> | ||
12 | #include <linux/ip.h> | ||
13 | #include <net/checksum.h> | ||
14 | |||
15 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
16 | #include <linux/netfilter_ipv6/ip6t_MARK.h> | ||
17 | |||
18 | MODULE_LICENSE("GPL"); | ||
19 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | ||
20 | |||
21 | static unsigned int | ||
22 | target(struct sk_buff **pskb, | ||
23 | const struct net_device *in, | ||
24 | const struct net_device *out, | ||
25 | unsigned int hooknum, | ||
26 | const void *targinfo, | ||
27 | void *userinfo) | ||
28 | { | ||
29 | const struct ip6t_mark_target_info *markinfo = targinfo; | ||
30 | |||
31 | if((*pskb)->nfmark != markinfo->mark) | ||
32 | (*pskb)->nfmark = markinfo->mark; | ||
33 | |||
34 | return IP6T_CONTINUE; | ||
35 | } | ||
36 | |||
37 | static int | ||
38 | checkentry(const char *tablename, | ||
39 | const struct ip6t_entry *e, | ||
40 | void *targinfo, | ||
41 | unsigned int targinfosize, | ||
42 | unsigned int hook_mask) | ||
43 | { | ||
44 | if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_mark_target_info))) { | ||
45 | printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", | ||
46 | targinfosize, | ||
47 | IP6T_ALIGN(sizeof(struct ip6t_mark_target_info))); | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | if (strcmp(tablename, "mangle") != 0) { | ||
52 | printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename); | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | return 1; | ||
57 | } | ||
58 | |||
59 | static struct ip6t_target ip6t_mark_reg = { | ||
60 | .name = "MARK", | ||
61 | .target = target, | ||
62 | .checkentry = checkentry, | ||
63 | .me = THIS_MODULE | ||
64 | }; | ||
65 | |||
66 | static int __init init(void) | ||
67 | { | ||
68 | printk(KERN_DEBUG "registering ipv6 mark target\n"); | ||
69 | if (ip6t_register_target(&ip6t_mark_reg)) | ||
70 | return -EINVAL; | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static void __exit fini(void) | ||
76 | { | ||
77 | ip6t_unregister_target(&ip6t_mark_reg); | ||
78 | } | ||
79 | |||
80 | module_init(init); | ||
81 | module_exit(fini); | ||
diff --git a/net/ipv6/netfilter/ip6t_NFQUEUE.c b/net/ipv6/netfilter/ip6t_NFQUEUE.c deleted file mode 100644 index c6e3730e7409..000000000000 --- a/net/ipv6/netfilter/ip6t_NFQUEUE.c +++ /dev/null | |||
@@ -1,70 +0,0 @@ | |||
1 | /* ip6tables module for using new netfilter netlink queue | ||
2 | * | ||
3 | * (C) 2005 by Harald Welte <laforge@netfilter.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | |||
14 | #include <linux/netfilter.h> | ||
15 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
16 | #include <linux/netfilter_ipv4/ipt_NFQUEUE.h> | ||
17 | |||
18 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | ||
19 | MODULE_DESCRIPTION("ip6tables NFQUEUE target"); | ||
20 | MODULE_LICENSE("GPL"); | ||
21 | |||
22 | static unsigned int | ||
23 | target(struct sk_buff **pskb, | ||
24 | const struct net_device *in, | ||
25 | const struct net_device *out, | ||
26 | unsigned int hooknum, | ||
27 | const void *targinfo, | ||
28 | void *userinfo) | ||
29 | { | ||
30 | const struct ipt_NFQ_info *tinfo = targinfo; | ||
31 | |||
32 | return NF_QUEUE_NR(tinfo->queuenum); | ||
33 | } | ||
34 | |||
35 | static int | ||
36 | checkentry(const char *tablename, | ||
37 | const struct ip6t_entry *e, | ||
38 | void *targinfo, | ||
39 | unsigned int targinfosize, | ||
40 | unsigned int hook_mask) | ||
41 | { | ||
42 | if (targinfosize != IP6T_ALIGN(sizeof(struct ipt_NFQ_info))) { | ||
43 | printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n", | ||
44 | targinfosize, | ||
45 | IP6T_ALIGN(sizeof(struct ipt_NFQ_info))); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | return 1; | ||
50 | } | ||
51 | |||
52 | static struct ip6t_target ipt_NFQ_reg = { | ||
53 | .name = "NFQUEUE", | ||
54 | .target = target, | ||
55 | .checkentry = checkentry, | ||
56 | .me = THIS_MODULE, | ||
57 | }; | ||
58 | |||
59 | static int __init init(void) | ||
60 | { | ||
61 | return ip6t_register_target(&ipt_NFQ_reg); | ||
62 | } | ||
63 | |||
64 | static void __exit fini(void) | ||
65 | { | ||
66 | ip6t_unregister_target(&ipt_NFQ_reg); | ||
67 | } | ||
68 | |||
69 | module_init(init); | ||
70 | module_exit(fini); | ||
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index b03e87adca93..c745717b4ce2 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -218,12 +218,13 @@ static unsigned int reject6_target(struct sk_buff **pskb, | |||
218 | } | 218 | } |
219 | 219 | ||
220 | static int check(const char *tablename, | 220 | static int check(const char *tablename, |
221 | const struct ip6t_entry *e, | 221 | const void *entry, |
222 | void *targinfo, | 222 | void *targinfo, |
223 | unsigned int targinfosize, | 223 | unsigned int targinfosize, |
224 | unsigned int hook_mask) | 224 | unsigned int hook_mask) |
225 | { | 225 | { |
226 | const struct ip6t_reject_info *rejinfo = targinfo; | 226 | const struct ip6t_reject_info *rejinfo = targinfo; |
227 | const struct ip6t_entry *e = entry; | ||
227 | 228 | ||
228 | if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) { | 229 | if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) { |
229 | DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize); | 230 | DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize); |
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index f5c1a7ff4a1f..219a30365dff 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c | |||
@@ -98,7 +98,7 @@ match(const struct sk_buff *skb, | |||
98 | /* Called when user tries to insert an entry of this type. */ | 98 | /* Called when user tries to insert an entry of this type. */ |
99 | static int | 99 | static int |
100 | checkentry(const char *tablename, | 100 | checkentry(const char *tablename, |
101 | const struct ip6t_ip6 *ip, | 101 | const void *entry, |
102 | void *matchinfo, | 102 | void *matchinfo, |
103 | unsigned int matchinfosize, | 103 | unsigned int matchinfosize, |
104 | unsigned int hook_mask) | 104 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c index 48cf5f9efc95..80fe82669ce2 100644 --- a/net/ipv6/netfilter/ip6t_dst.c +++ b/net/ipv6/netfilter/ip6t_dst.c | |||
@@ -178,7 +178,7 @@ match(const struct sk_buff *skb, | |||
178 | /* Called when user tries to insert an entry of this type. */ | 178 | /* Called when user tries to insert an entry of this type. */ |
179 | static int | 179 | static int |
180 | checkentry(const char *tablename, | 180 | checkentry(const char *tablename, |
181 | const struct ip6t_ip6 *ip, | 181 | const void *info, |
182 | void *matchinfo, | 182 | void *matchinfo, |
183 | unsigned int matchinfosize, | 183 | unsigned int matchinfosize, |
184 | unsigned int hook_mask) | 184 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c index e1828f6d0a40..724285df8711 100644 --- a/net/ipv6/netfilter/ip6t_esp.c +++ b/net/ipv6/netfilter/ip6t_esp.c | |||
@@ -76,7 +76,7 @@ match(const struct sk_buff *skb, | |||
76 | /* Called when user tries to insert an entry of this type. */ | 76 | /* Called when user tries to insert an entry of this type. */ |
77 | static int | 77 | static int |
78 | checkentry(const char *tablename, | 78 | checkentry(const char *tablename, |
79 | const struct ip6t_ip6 *ip, | 79 | const void *ip, |
80 | void *matchinfo, | 80 | void *matchinfo, |
81 | unsigned int matchinfosize, | 81 | unsigned int matchinfosize, |
82 | unsigned int hook_mask) | 82 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c index 616c2cbcd54d..ddf5f571909c 100644 --- a/net/ipv6/netfilter/ip6t_eui64.c +++ b/net/ipv6/netfilter/ip6t_eui64.c | |||
@@ -62,7 +62,7 @@ match(const struct sk_buff *skb, | |||
62 | 62 | ||
63 | static int | 63 | static int |
64 | ip6t_eui64_checkentry(const char *tablename, | 64 | ip6t_eui64_checkentry(const char *tablename, |
65 | const struct ip6t_ip6 *ip, | 65 | const void *ip, |
66 | void *matchinfo, | 66 | void *matchinfo, |
67 | unsigned int matchsize, | 67 | unsigned int matchsize, |
68 | unsigned int hook_mask) | 68 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index d1549b268669..a9964b946ed5 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c | |||
@@ -115,7 +115,7 @@ match(const struct sk_buff *skb, | |||
115 | /* Called when user tries to insert an entry of this type. */ | 115 | /* Called when user tries to insert an entry of this type. */ |
116 | static int | 116 | static int |
117 | checkentry(const char *tablename, | 117 | checkentry(const char *tablename, |
118 | const struct ip6t_ip6 *ip, | 118 | const void *ip, |
119 | void *matchinfo, | 119 | void *matchinfo, |
120 | unsigned int matchinfosize, | 120 | unsigned int matchinfosize, |
121 | unsigned int hook_mask) | 121 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index e3bc8e2700e7..ed8ded18bbd4 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c | |||
@@ -178,7 +178,7 @@ match(const struct sk_buff *skb, | |||
178 | /* Called when user tries to insert an entry of this type. */ | 178 | /* Called when user tries to insert an entry of this type. */ |
179 | static int | 179 | static int |
180 | checkentry(const char *tablename, | 180 | checkentry(const char *tablename, |
181 | const struct ip6t_ip6 *ip, | 181 | const void *entry, |
182 | void *matchinfo, | 182 | void *matchinfo, |
183 | unsigned int matchinfosize, | 183 | unsigned int matchinfosize, |
184 | unsigned int hook_mask) | 184 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c index 0beaff5471dd..c5d9079f2d9d 100644 --- a/net/ipv6/netfilter/ip6t_hl.c +++ b/net/ipv6/netfilter/ip6t_hl.c | |||
@@ -48,7 +48,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, | |||
48 | return 0; | 48 | return 0; |
49 | } | 49 | } |
50 | 50 | ||
51 | static int checkentry(const char *tablename, const struct ip6t_ip6 *ip, | 51 | static int checkentry(const char *tablename, const void *entry, |
52 | void *matchinfo, unsigned int matchsize, | 52 | void *matchinfo, unsigned int matchsize, |
53 | unsigned int hook_mask) | 53 | unsigned int hook_mask) |
54 | { | 54 | { |
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c index 32e67f05845b..fda1ceaf5a29 100644 --- a/net/ipv6/netfilter/ip6t_ipv6header.c +++ b/net/ipv6/netfilter/ip6t_ipv6header.c | |||
@@ -124,7 +124,7 @@ ipv6header_match(const struct sk_buff *skb, | |||
124 | 124 | ||
125 | static int | 125 | static int |
126 | ipv6header_checkentry(const char *tablename, | 126 | ipv6header_checkentry(const char *tablename, |
127 | const struct ip6t_ip6 *ip, | 127 | const void *ip, |
128 | void *matchinfo, | 128 | void *matchinfo, |
129 | unsigned int matchsize, | 129 | unsigned int matchsize, |
130 | unsigned int hook_mask) | 130 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_length.c b/net/ipv6/netfilter/ip6t_length.c deleted file mode 100644 index e0537d3811d5..000000000000 --- a/net/ipv6/netfilter/ip6t_length.c +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | /* Length Match - IPv6 Port */ | ||
2 | |||
3 | /* (C) 1999-2001 James Morris <jmorros@intercode.com.au> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | #include <linux/netfilter_ipv6/ip6t_length.h> | ||
14 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
15 | |||
16 | MODULE_LICENSE("GPL"); | ||
17 | MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); | ||
18 | MODULE_DESCRIPTION("IPv6 packet length match"); | ||
19 | |||
20 | static int | ||
21 | match(const struct sk_buff *skb, | ||
22 | const struct net_device *in, | ||
23 | const struct net_device *out, | ||
24 | const void *matchinfo, | ||
25 | int offset, | ||
26 | unsigned int protoff, | ||
27 | int *hotdrop) | ||
28 | { | ||
29 | const struct ip6t_length_info *info = matchinfo; | ||
30 | u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr); | ||
31 | |||
32 | return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; | ||
33 | } | ||
34 | |||
35 | static int | ||
36 | checkentry(const char *tablename, | ||
37 | const struct ip6t_ip6 *ip, | ||
38 | void *matchinfo, | ||
39 | unsigned int matchsize, | ||
40 | unsigned int hook_mask) | ||
41 | { | ||
42 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_length_info))) | ||
43 | return 0; | ||
44 | |||
45 | return 1; | ||
46 | } | ||
47 | |||
48 | static struct ip6t_match length_match = { | ||
49 | .name = "length", | ||
50 | .match = &match, | ||
51 | .checkentry = &checkentry, | ||
52 | .me = THIS_MODULE, | ||
53 | }; | ||
54 | |||
55 | static int __init init(void) | ||
56 | { | ||
57 | return ip6t_register_match(&length_match); | ||
58 | } | ||
59 | |||
60 | static void __exit fini(void) | ||
61 | { | ||
62 | ip6t_unregister_match(&length_match); | ||
63 | } | ||
64 | |||
65 | module_init(init); | ||
66 | module_exit(fini); | ||
diff --git a/net/ipv6/netfilter/ip6t_limit.c b/net/ipv6/netfilter/ip6t_limit.c deleted file mode 100644 index fb782f610be2..000000000000 --- a/net/ipv6/netfilter/ip6t_limit.c +++ /dev/null | |||
@@ -1,147 +0,0 @@ | |||
1 | /* Kernel module to control the rate | ||
2 | * | ||
3 | * 2 September 1999: Changed from the target RATE to the match | ||
4 | * `limit', removed logging. Did I mention that | ||
5 | * Alexey is a fucking genius? | ||
6 | * Rusty Russell (rusty@rustcorp.com.au). */ | ||
7 | |||
8 | /* (C) 1999 Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr> | ||
9 | * (C) 1999 Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/skbuff.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | |||
21 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
22 | #include <linux/netfilter_ipv6/ip6t_limit.h> | ||
23 | |||
24 | MODULE_LICENSE("GPL"); | ||
25 | MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>"); | ||
26 | MODULE_DESCRIPTION("rate limiting within ip6tables"); | ||
27 | |||
28 | /* The algorithm used is the Simple Token Bucket Filter (TBF) | ||
29 | * see net/sched/sch_tbf.c in the linux source tree | ||
30 | */ | ||
31 | |||
32 | static DEFINE_SPINLOCK(limit_lock); | ||
33 | |||
34 | /* Rusty: This is my (non-mathematically-inclined) understanding of | ||
35 | this algorithm. The `average rate' in jiffies becomes your initial | ||
36 | amount of credit `credit' and the most credit you can ever have | ||
37 | `credit_cap'. The `peak rate' becomes the cost of passing the | ||
38 | test, `cost'. | ||
39 | |||
40 | `prev' tracks the last packet hit: you gain one credit per jiffy. | ||
41 | If you get credit balance more than this, the extra credit is | ||
42 | discarded. Every time the match passes, you lose `cost' credits; | ||
43 | if you don't have that many, the test fails. | ||
44 | |||
45 | See Alexey's formal explanation in net/sched/sch_tbf.c. | ||
46 | |||
47 | To avoid underflow, we multiply by 128 (ie. you get 128 credits per | ||
48 | jiffy). Hence a cost of 2^32-1, means one pass per 32768 seconds | ||
49 | at 1024HZ (or one every 9 hours). A cost of 1 means 12800 passes | ||
50 | per second at 100HZ. */ | ||
51 | |||
52 | #define CREDITS_PER_JIFFY 128 | ||
53 | |||
54 | static int | ||
55 | ip6t_limit_match(const struct sk_buff *skb, | ||
56 | const struct net_device *in, | ||
57 | const struct net_device *out, | ||
58 | const void *matchinfo, | ||
59 | int offset, | ||
60 | unsigned int protoff, | ||
61 | int *hotdrop) | ||
62 | { | ||
63 | struct ip6t_rateinfo *r = ((struct ip6t_rateinfo *)matchinfo)->master; | ||
64 | unsigned long now = jiffies; | ||
65 | |||
66 | spin_lock_bh(&limit_lock); | ||
67 | r->credit += (now - xchg(&r->prev, now)) * CREDITS_PER_JIFFY; | ||
68 | if (r->credit > r->credit_cap) | ||
69 | r->credit = r->credit_cap; | ||
70 | |||
71 | if (r->credit >= r->cost) { | ||
72 | /* We're not limited. */ | ||
73 | r->credit -= r->cost; | ||
74 | spin_unlock_bh(&limit_lock); | ||
75 | return 1; | ||
76 | } | ||
77 | |||
78 | spin_unlock_bh(&limit_lock); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | /* Precision saver. */ | ||
83 | static u_int32_t | ||
84 | user2credits(u_int32_t user) | ||
85 | { | ||
86 | /* If multiplying would overflow... */ | ||
87 | if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) | ||
88 | /* Divide first. */ | ||
89 | return (user / IP6T_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; | ||
90 | |||
91 | return (user * HZ * CREDITS_PER_JIFFY) / IP6T_LIMIT_SCALE; | ||
92 | } | ||
93 | |||
94 | static int | ||
95 | ip6t_limit_checkentry(const char *tablename, | ||
96 | const struct ip6t_ip6 *ip, | ||
97 | void *matchinfo, | ||
98 | unsigned int matchsize, | ||
99 | unsigned int hook_mask) | ||
100 | { | ||
101 | struct ip6t_rateinfo *r = matchinfo; | ||
102 | |||
103 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rateinfo))) | ||
104 | return 0; | ||
105 | |||
106 | /* Check for overflow. */ | ||
107 | if (r->burst == 0 | ||
108 | || user2credits(r->avg * r->burst) < user2credits(r->avg)) { | ||
109 | printk("Call rusty: overflow in ip6t_limit: %u/%u\n", | ||
110 | r->avg, r->burst); | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | /* User avg in seconds * IP6T_LIMIT_SCALE: convert to jiffies * | ||
115 | 128. */ | ||
116 | r->prev = jiffies; | ||
117 | r->credit = user2credits(r->avg * r->burst); /* Credits full. */ | ||
118 | r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */ | ||
119 | r->cost = user2credits(r->avg); | ||
120 | |||
121 | /* For SMP, we only want to use one set of counters. */ | ||
122 | r->master = r; | ||
123 | |||
124 | return 1; | ||
125 | } | ||
126 | |||
127 | static struct ip6t_match ip6t_limit_reg = { | ||
128 | .name = "limit", | ||
129 | .match = ip6t_limit_match, | ||
130 | .checkentry = ip6t_limit_checkentry, | ||
131 | .me = THIS_MODULE, | ||
132 | }; | ||
133 | |||
134 | static int __init init(void) | ||
135 | { | ||
136 | if (ip6t_register_match(&ip6t_limit_reg)) | ||
137 | return -EINVAL; | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static void __exit fini(void) | ||
142 | { | ||
143 | ip6t_unregister_match(&ip6t_limit_reg); | ||
144 | } | ||
145 | |||
146 | module_init(init); | ||
147 | module_exit(fini); | ||
diff --git a/net/ipv6/netfilter/ip6t_mac.c b/net/ipv6/netfilter/ip6t_mac.c deleted file mode 100644 index c848152315bc..000000000000 --- a/net/ipv6/netfilter/ip6t_mac.c +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | /* Kernel module to match MAC address parameters. */ | ||
2 | |||
3 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
4 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | #include <linux/if_ether.h> | ||
14 | #include <linux/etherdevice.h> | ||
15 | |||
16 | #include <linux/netfilter_ipv6/ip6t_mac.h> | ||
17 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
18 | |||
19 | MODULE_LICENSE("GPL"); | ||
20 | MODULE_DESCRIPTION("MAC address matching module for IPv6"); | ||
21 | MODULE_AUTHOR("Netfilter Core Teaam <coreteam@netfilter.org>"); | ||
22 | |||
23 | static int | ||
24 | match(const struct sk_buff *skb, | ||
25 | const struct net_device *in, | ||
26 | const struct net_device *out, | ||
27 | const void *matchinfo, | ||
28 | int offset, | ||
29 | unsigned int protoff, | ||
30 | int *hotdrop) | ||
31 | { | ||
32 | const struct ip6t_mac_info *info = matchinfo; | ||
33 | |||
34 | /* Is mac pointer valid? */ | ||
35 | return (skb->mac.raw >= skb->head | ||
36 | && (skb->mac.raw + ETH_HLEN) <= skb->data | ||
37 | /* If so, compare... */ | ||
38 | && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr)) | ||
39 | ^ info->invert)); | ||
40 | } | ||
41 | |||
42 | static int | ||
43 | ip6t_mac_checkentry(const char *tablename, | ||
44 | const struct ip6t_ip6 *ip, | ||
45 | void *matchinfo, | ||
46 | unsigned int matchsize, | ||
47 | unsigned int hook_mask) | ||
48 | { | ||
49 | if (hook_mask | ||
50 | & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) | ||
51 | | (1 << NF_IP6_FORWARD))) { | ||
52 | printk("ip6t_mac: only valid for PRE_ROUTING, LOCAL_IN or" | ||
53 | " FORWARD\n"); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mac_info))) | ||
58 | return 0; | ||
59 | |||
60 | return 1; | ||
61 | } | ||
62 | |||
63 | static struct ip6t_match mac_match = { | ||
64 | .name = "mac", | ||
65 | .match = &match, | ||
66 | .checkentry = &ip6t_mac_checkentry, | ||
67 | .me = THIS_MODULE, | ||
68 | }; | ||
69 | |||
70 | static int __init init(void) | ||
71 | { | ||
72 | return ip6t_register_match(&mac_match); | ||
73 | } | ||
74 | |||
75 | static void __exit fini(void) | ||
76 | { | ||
77 | ip6t_unregister_match(&mac_match); | ||
78 | } | ||
79 | |||
80 | module_init(init); | ||
81 | module_exit(fini); | ||
diff --git a/net/ipv6/netfilter/ip6t_mark.c b/net/ipv6/netfilter/ip6t_mark.c deleted file mode 100644 index affc3de364fc..000000000000 --- a/net/ipv6/netfilter/ip6t_mark.c +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | /* Kernel module to match NFMARK values. */ | ||
2 | |||
3 | /* (C) 1999-2001 Marc Boucher <marc@mbsi.ca> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | |||
14 | #include <linux/netfilter_ipv6/ip6t_mark.h> | ||
15 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
16 | |||
17 | MODULE_LICENSE("GPL"); | ||
18 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | ||
19 | MODULE_DESCRIPTION("ip6tables mark match"); | ||
20 | |||
21 | static int | ||
22 | match(const struct sk_buff *skb, | ||
23 | const struct net_device *in, | ||
24 | const struct net_device *out, | ||
25 | const void *matchinfo, | ||
26 | int offset, | ||
27 | unsigned int protoff, | ||
28 | int *hotdrop) | ||
29 | { | ||
30 | const struct ip6t_mark_info *info = matchinfo; | ||
31 | |||
32 | return ((skb->nfmark & info->mask) == info->mark) ^ info->invert; | ||
33 | } | ||
34 | |||
35 | static int | ||
36 | checkentry(const char *tablename, | ||
37 | const struct ip6t_ip6 *ip, | ||
38 | void *matchinfo, | ||
39 | unsigned int matchsize, | ||
40 | unsigned int hook_mask) | ||
41 | { | ||
42 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mark_info))) | ||
43 | return 0; | ||
44 | |||
45 | return 1; | ||
46 | } | ||
47 | |||
48 | static struct ip6t_match mark_match = { | ||
49 | .name = "mark", | ||
50 | .match = &match, | ||
51 | .checkentry = &checkentry, | ||
52 | .me = THIS_MODULE, | ||
53 | }; | ||
54 | |||
55 | static int __init init(void) | ||
56 | { | ||
57 | return ip6t_register_match(&mark_match); | ||
58 | } | ||
59 | |||
60 | static void __exit fini(void) | ||
61 | { | ||
62 | ip6t_unregister_match(&mark_match); | ||
63 | } | ||
64 | |||
65 | module_init(init); | ||
66 | module_exit(fini); | ||
diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c index 6e3246153fa3..49f7829dfbc2 100644 --- a/net/ipv6/netfilter/ip6t_multiport.c +++ b/net/ipv6/netfilter/ip6t_multiport.c | |||
@@ -84,11 +84,12 @@ match(const struct sk_buff *skb, | |||
84 | /* Called when user tries to insert an entry of this type. */ | 84 | /* Called when user tries to insert an entry of this type. */ |
85 | static int | 85 | static int |
86 | checkentry(const char *tablename, | 86 | checkentry(const char *tablename, |
87 | const struct ip6t_ip6 *ip, | 87 | const void *info, |
88 | void *matchinfo, | 88 | void *matchinfo, |
89 | unsigned int matchsize, | 89 | unsigned int matchsize, |
90 | unsigned int hook_mask) | 90 | unsigned int hook_mask) |
91 | { | 91 | { |
92 | const struct ip6t_ip6 *ip = info; | ||
92 | const struct ip6t_multiport *multiinfo = matchinfo; | 93 | const struct ip6t_multiport *multiinfo = matchinfo; |
93 | 94 | ||
94 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport))) | 95 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport))) |
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c index 4de4cdad4b7d..5409b375b512 100644 --- a/net/ipv6/netfilter/ip6t_owner.c +++ b/net/ipv6/netfilter/ip6t_owner.c | |||
@@ -53,7 +53,7 @@ match(const struct sk_buff *skb, | |||
53 | 53 | ||
54 | static int | 54 | static int |
55 | checkentry(const char *tablename, | 55 | checkentry(const char *tablename, |
56 | const struct ip6t_ip6 *ip, | 56 | const void *ip, |
57 | void *matchinfo, | 57 | void *matchinfo, |
58 | unsigned int matchsize, | 58 | unsigned int matchsize, |
59 | unsigned int hook_mask) | 59 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index c1e770e45543..8465b4375855 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c | |||
@@ -183,7 +183,7 @@ match(const struct sk_buff *skb, | |||
183 | /* Called when user tries to insert an entry of this type. */ | 183 | /* Called when user tries to insert an entry of this type. */ |
184 | static int | 184 | static int |
185 | checkentry(const char *tablename, | 185 | checkentry(const char *tablename, |
186 | const struct ip6t_ip6 *ip, | 186 | const void *entry, |
187 | void *matchinfo, | 187 | void *matchinfo, |
188 | unsigned int matchinfosize, | 188 | unsigned int matchinfosize, |
189 | unsigned int hook_mask) | 189 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 4c0028671c20..ce4a968e1f70 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -97,6 +97,7 @@ static struct ip6t_table packet_filter = { | |||
97 | .valid_hooks = FILTER_VALID_HOOKS, | 97 | .valid_hooks = FILTER_VALID_HOOKS, |
98 | .lock = RW_LOCK_UNLOCKED, | 98 | .lock = RW_LOCK_UNLOCKED, |
99 | .me = THIS_MODULE, | 99 | .me = THIS_MODULE, |
100 | .af = AF_INET6, | ||
100 | }; | 101 | }; |
101 | 102 | ||
102 | /* The work comes in here from netfilter.c. */ | 103 | /* The work comes in here from netfilter.c. */ |
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 85c1e6eada19..30a4627e000d 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -127,6 +127,7 @@ static struct ip6t_table packet_mangler = { | |||
127 | .valid_hooks = MANGLE_VALID_HOOKS, | 127 | .valid_hooks = MANGLE_VALID_HOOKS, |
128 | .lock = RW_LOCK_UNLOCKED, | 128 | .lock = RW_LOCK_UNLOCKED, |
129 | .me = THIS_MODULE, | 129 | .me = THIS_MODULE, |
130 | .af = AF_INET6, | ||
130 | }; | 131 | }; |
131 | 132 | ||
132 | /* The work comes in here from netfilter.c. */ | 133 | /* The work comes in here from netfilter.c. */ |
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index c2982efd14af..db28ba3855e2 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c | |||
@@ -106,11 +106,12 @@ static struct | |||
106 | } | 106 | } |
107 | }; | 107 | }; |
108 | 108 | ||
109 | static struct ip6t_table packet_raw = { | 109 | static struct xt_table packet_raw = { |
110 | .name = "raw", | 110 | .name = "raw", |
111 | .valid_hooks = RAW_VALID_HOOKS, | 111 | .valid_hooks = RAW_VALID_HOOKS, |
112 | .lock = RW_LOCK_UNLOCKED, | 112 | .lock = RW_LOCK_UNLOCKED, |
113 | .me = THIS_MODULE | 113 | .me = THIS_MODULE, |
114 | .af = AF_INET6, | ||
114 | }; | 115 | }; |
115 | 116 | ||
116 | /* The work comes in here from netfilter.c. */ | 117 | /* The work comes in here from netfilter.c. */ |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index e57d6fc9957a..ac702a29dd16 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -74,7 +74,7 @@ static int ipv6_invert_tuple(struct nf_conntrack_tuple *tuple, | |||
74 | static int ipv6_print_tuple(struct seq_file *s, | 74 | static int ipv6_print_tuple(struct seq_file *s, |
75 | const struct nf_conntrack_tuple *tuple) | 75 | const struct nf_conntrack_tuple *tuple) |
76 | { | 76 | { |
77 | return seq_printf(s, "src=%x:%x:%x:%x:%x:%x:%x:%x dst=%x:%x:%x:%x:%x:%x:%x:%x ", | 77 | return seq_printf(s, "src=" NIP6_FMT " dst=" NIP6_FMT " ", |
78 | NIP6(*((struct in6_addr *)tuple->src.u3.ip6)), | 78 | NIP6(*((struct in6_addr *)tuple->src.u3.ip6)), |
79 | NIP6(*((struct in6_addr *)tuple->dst.u3.ip6))); | 79 | NIP6(*((struct in6_addr *)tuple->dst.u3.ip6))); |
80 | } | 80 | } |
@@ -584,7 +584,7 @@ MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); | |||
584 | 584 | ||
585 | static int __init init(void) | 585 | static int __init init(void) |
586 | { | 586 | { |
587 | need_nf_conntrack(); | 587 | need_conntrack(); |
588 | return init_or_cleanup(1); | 588 | return init_or_cleanup(1); |
589 | } | 589 | } |
590 | 590 | ||
@@ -595,9 +595,3 @@ static void __exit fini(void) | |||
595 | 595 | ||
596 | module_init(init); | 596 | module_init(init); |
597 | module_exit(fini); | 597 | module_exit(fini); |
598 | |||
599 | void need_ip6_conntrack(void) | ||
600 | { | ||
601 | } | ||
602 | |||
603 | EXPORT_SYMBOL(need_ip6_conntrack); | ||
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index f3e5ffbd592f..84ef9a13108d 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -70,8 +70,8 @@ struct nf_ct_frag6_skb_cb | |||
70 | 70 | ||
71 | struct nf_ct_frag6_queue | 71 | struct nf_ct_frag6_queue |
72 | { | 72 | { |
73 | struct nf_ct_frag6_queue *next; | 73 | struct hlist_node list; |
74 | struct list_head lru_list; /* lru list member */ | 74 | struct list_head lru_list; /* lru list member */ |
75 | 75 | ||
76 | __u32 id; /* fragment id */ | 76 | __u32 id; /* fragment id */ |
77 | struct in6_addr saddr; | 77 | struct in6_addr saddr; |
@@ -90,14 +90,13 @@ struct nf_ct_frag6_queue | |||
90 | #define FIRST_IN 2 | 90 | #define FIRST_IN 2 |
91 | #define LAST_IN 1 | 91 | #define LAST_IN 1 |
92 | __u16 nhoffset; | 92 | __u16 nhoffset; |
93 | struct nf_ct_frag6_queue **pprev; | ||
94 | }; | 93 | }; |
95 | 94 | ||
96 | /* Hash table. */ | 95 | /* Hash table. */ |
97 | 96 | ||
98 | #define FRAG6Q_HASHSZ 64 | 97 | #define FRAG6Q_HASHSZ 64 |
99 | 98 | ||
100 | static struct nf_ct_frag6_queue *nf_ct_frag6_hash[FRAG6Q_HASHSZ]; | 99 | static struct hlist_head nf_ct_frag6_hash[FRAG6Q_HASHSZ]; |
101 | static DEFINE_RWLOCK(nf_ct_frag6_lock); | 100 | static DEFINE_RWLOCK(nf_ct_frag6_lock); |
102 | static u32 nf_ct_frag6_hash_rnd; | 101 | static u32 nf_ct_frag6_hash_rnd; |
103 | static LIST_HEAD(nf_ct_frag6_lru_list); | 102 | static LIST_HEAD(nf_ct_frag6_lru_list); |
@@ -105,9 +104,7 @@ int nf_ct_frag6_nqueues = 0; | |||
105 | 104 | ||
106 | static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq) | 105 | static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq) |
107 | { | 106 | { |
108 | if (fq->next) | 107 | hlist_del(&fq->list); |
109 | fq->next->pprev = fq->pprev; | ||
110 | *fq->pprev = fq->next; | ||
111 | list_del(&fq->lru_list); | 108 | list_del(&fq->lru_list); |
112 | nf_ct_frag6_nqueues--; | 109 | nf_ct_frag6_nqueues--; |
113 | } | 110 | } |
@@ -158,28 +155,18 @@ static void nf_ct_frag6_secret_rebuild(unsigned long dummy) | |||
158 | get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32)); | 155 | get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32)); |
159 | for (i = 0; i < FRAG6Q_HASHSZ; i++) { | 156 | for (i = 0; i < FRAG6Q_HASHSZ; i++) { |
160 | struct nf_ct_frag6_queue *q; | 157 | struct nf_ct_frag6_queue *q; |
158 | struct hlist_node *p, *n; | ||
161 | 159 | ||
162 | q = nf_ct_frag6_hash[i]; | 160 | hlist_for_each_entry_safe(q, p, n, &nf_ct_frag6_hash[i], list) { |
163 | while (q) { | ||
164 | struct nf_ct_frag6_queue *next = q->next; | ||
165 | unsigned int hval = ip6qhashfn(q->id, | 161 | unsigned int hval = ip6qhashfn(q->id, |
166 | &q->saddr, | 162 | &q->saddr, |
167 | &q->daddr); | 163 | &q->daddr); |
168 | |||
169 | if (hval != i) { | 164 | if (hval != i) { |
170 | /* Unlink. */ | 165 | hlist_del(&q->list); |
171 | if (q->next) | ||
172 | q->next->pprev = q->pprev; | ||
173 | *q->pprev = q->next; | ||
174 | |||
175 | /* Relink to new hash chain. */ | 166 | /* Relink to new hash chain. */ |
176 | if ((q->next = nf_ct_frag6_hash[hval]) != NULL) | 167 | hlist_add_head(&q->list, |
177 | q->next->pprev = &q->next; | 168 | &nf_ct_frag6_hash[hval]); |
178 | nf_ct_frag6_hash[hval] = q; | ||
179 | q->pprev = &nf_ct_frag6_hash[hval]; | ||
180 | } | 169 | } |
181 | |||
182 | q = next; | ||
183 | } | 170 | } |
184 | } | 171 | } |
185 | write_unlock(&nf_ct_frag6_lock); | 172 | write_unlock(&nf_ct_frag6_lock); |
@@ -314,15 +301,17 @@ out: | |||
314 | 301 | ||
315 | /* Creation primitives. */ | 302 | /* Creation primitives. */ |
316 | 303 | ||
317 | |||
318 | static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, | 304 | static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, |
319 | struct nf_ct_frag6_queue *fq_in) | 305 | struct nf_ct_frag6_queue *fq_in) |
320 | { | 306 | { |
321 | struct nf_ct_frag6_queue *fq; | 307 | struct nf_ct_frag6_queue *fq; |
308 | #ifdef CONFIG_SMP | ||
309 | struct hlist_node *n; | ||
310 | #endif | ||
322 | 311 | ||
323 | write_lock(&nf_ct_frag6_lock); | 312 | write_lock(&nf_ct_frag6_lock); |
324 | #ifdef CONFIG_SMP | 313 | #ifdef CONFIG_SMP |
325 | for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) { | 314 | hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) { |
326 | if (fq->id == fq_in->id && | 315 | if (fq->id == fq_in->id && |
327 | !ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) && | 316 | !ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) && |
328 | !ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) { | 317 | !ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) { |
@@ -340,10 +329,7 @@ static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, | |||
340 | atomic_inc(&fq->refcnt); | 329 | atomic_inc(&fq->refcnt); |
341 | 330 | ||
342 | atomic_inc(&fq->refcnt); | 331 | atomic_inc(&fq->refcnt); |
343 | if ((fq->next = nf_ct_frag6_hash[hash]) != NULL) | 332 | hlist_add_head(&fq->list, &nf_ct_frag6_hash[hash]); |
344 | fq->next->pprev = &fq->next; | ||
345 | nf_ct_frag6_hash[hash] = fq; | ||
346 | fq->pprev = &nf_ct_frag6_hash[hash]; | ||
347 | INIT_LIST_HEAD(&fq->lru_list); | 333 | INIT_LIST_HEAD(&fq->lru_list); |
348 | list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list); | 334 | list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list); |
349 | nf_ct_frag6_nqueues++; | 335 | nf_ct_frag6_nqueues++; |
@@ -384,10 +370,11 @@ static __inline__ struct nf_ct_frag6_queue * | |||
384 | fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) | 370 | fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) |
385 | { | 371 | { |
386 | struct nf_ct_frag6_queue *fq; | 372 | struct nf_ct_frag6_queue *fq; |
373 | struct hlist_node *n; | ||
387 | unsigned int hash = ip6qhashfn(id, src, dst); | 374 | unsigned int hash = ip6qhashfn(id, src, dst); |
388 | 375 | ||
389 | read_lock(&nf_ct_frag6_lock); | 376 | read_lock(&nf_ct_frag6_lock); |
390 | for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) { | 377 | hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) { |
391 | if (fq->id == id && | 378 | if (fq->id == id && |
392 | !ipv6_addr_cmp(src, &fq->saddr) && | 379 | !ipv6_addr_cmp(src, &fq->saddr) && |
393 | !ipv6_addr_cmp(dst, &fq->daddr)) { | 380 | !ipv6_addr_cmp(dst, &fq->daddr)) { |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index bf0d0abc3871..a5723024d3b3 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/pfkeyv2.h> | 15 | #include <linux/pfkeyv2.h> |
16 | #include <linux/ipsec.h> | 16 | #include <linux/ipsec.h> |
17 | #include <net/ipv6.h> | 17 | #include <net/ipv6.h> |
18 | #include <net/addrconf.h> | ||
18 | 19 | ||
19 | static struct xfrm_state_afinfo xfrm6_state_afinfo; | 20 | static struct xfrm_state_afinfo xfrm6_state_afinfo; |
20 | 21 | ||
@@ -41,6 +42,22 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
41 | memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr)); | 42 | memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr)); |
42 | if (ipv6_addr_any((struct in6_addr*)&x->props.saddr)) | 43 | if (ipv6_addr_any((struct in6_addr*)&x->props.saddr)) |
43 | memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr)); | 44 | memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr)); |
45 | if (tmpl->mode && ipv6_addr_any((struct in6_addr*)&x->props.saddr)) { | ||
46 | struct rt6_info *rt; | ||
47 | struct flowi fl_tunnel = { | ||
48 | .nl_u = { | ||
49 | .ip6_u = { | ||
50 | .daddr = *(struct in6_addr *)daddr, | ||
51 | } | ||
52 | } | ||
53 | }; | ||
54 | if (!xfrm_dst_lookup((struct xfrm_dst **)&rt, | ||
55 | &fl_tunnel, AF_INET6)) { | ||
56 | ipv6_get_saddr(&rt->u.dst, (struct in6_addr *)daddr, | ||
57 | (struct in6_addr *)&x->props.saddr); | ||
58 | dst_release(&rt->u.dst); | ||
59 | } | ||
60 | } | ||
44 | x->props.mode = tmpl->mode; | 61 | x->props.mode = tmpl->mode; |
45 | x->props.reqid = tmpl->reqid; | 62 | x->props.reqid = tmpl->reqid; |
46 | x->props.family = AF_INET6; | 63 | x->props.family = AF_INET6; |
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index da09ff258648..8cfc58b96fc2 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -259,8 +259,7 @@ try_next_2:; | |||
259 | spi = 0; | 259 | spi = 0; |
260 | goto out; | 260 | goto out; |
261 | alloc_spi: | 261 | alloc_spi: |
262 | X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for " | 262 | X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for " NIP6_FMT "\n", |
263 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
264 | __FUNCTION__, | 263 | __FUNCTION__, |
265 | NIP6(*(struct in6_addr *)saddr)); | 264 | NIP6(*(struct in6_addr *)saddr)); |
266 | x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, SLAB_ATOMIC); | 265 | x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, SLAB_ATOMIC); |
@@ -323,9 +322,8 @@ void xfrm6_tunnel_free_spi(xfrm_address_t *saddr) | |||
323 | list_byaddr) | 322 | list_byaddr) |
324 | { | 323 | { |
325 | if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) { | 324 | if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) { |
326 | X6TPRINTK3(KERN_DEBUG "%s(): x6spi object " | 325 | X6TPRINTK3(KERN_DEBUG "%s(): x6spi object for " NIP6_FMT |
327 | "for %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " | 326 | " found at %p\n", |
328 | "found at %p\n", | ||
329 | __FUNCTION__, | 327 | __FUNCTION__, |
330 | NIP6(*(struct in6_addr *)saddr), | 328 | NIP6(*(struct in6_addr *)saddr), |
331 | x6spi); | 329 | x6spi); |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 7d55f9cbd853..99c0a0fa4a97 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -103,3 +103,261 @@ config NF_CT_NETLINK | |||
103 | This option enables support for a netlink-based userspace interface | 103 | This option enables support for a netlink-based userspace interface |
104 | 104 | ||
105 | endmenu | 105 | endmenu |
106 | |||
107 | config NETFILTER_XTABLES | ||
108 | tristate "Netfilter Xtables support (required for ip_tables)" | ||
109 | help | ||
110 | This is required if you intend to use any of ip_tables, | ||
111 | ip6_tables or arp_tables. | ||
112 | |||
113 | # alphabetically ordered list of targets | ||
114 | |||
115 | config NETFILTER_XT_TARGET_CLASSIFY | ||
116 | tristate '"CLASSIFY" target support' | ||
117 | depends on NETFILTER_XTABLES | ||
118 | help | ||
119 | This option adds a `CLASSIFY' target, which enables the user to set | ||
120 | the priority of a packet. Some qdiscs can use this value for | ||
121 | classification, among these are: | ||
122 | |||
123 | atm, cbq, dsmark, pfifo_fast, htb, prio | ||
124 | |||
125 | To compile it as a module, choose M here. If unsure, say N. | ||
126 | |||
127 | config NETFILTER_XT_TARGET_CONNMARK | ||
128 | tristate '"CONNMARK" target support' | ||
129 | depends on NETFILTER_XTABLES | ||
130 | depends on IP_NF_MANGLE || IP6_NF_MANGLE | ||
131 | depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) | ||
132 | help | ||
133 | This option adds a `CONNMARK' target, which allows one to manipulate | ||
134 | the connection mark value. Similar to the MARK target, but | ||
135 | affects the connection mark value rather than the packet mark value. | ||
136 | |||
137 | If you want to compile it as a module, say M here and read | ||
138 | <file:Documentation/modules.txt>. The module will be called | ||
139 | ipt_CONNMARK.o. If unsure, say `N'. | ||
140 | |||
141 | config NETFILTER_XT_TARGET_MARK | ||
142 | tristate '"MARK" target support' | ||
143 | depends on NETFILTER_XTABLES | ||
144 | help | ||
145 | This option adds a `MARK' target, which allows you to create rules | ||
146 | in the `mangle' table which alter the netfilter mark (nfmark) field | ||
147 | associated with the packet prior to routing. This can change | ||
148 | the routing method (see `Use netfilter MARK value as routing | ||
149 | key') and can also be used by other subsystems to change their | ||
150 | behavior. | ||
151 | |||
152 | To compile it as a module, choose M here. If unsure, say N. | ||
153 | |||
154 | config NETFILTER_XT_TARGET_NFQUEUE | ||
155 | tristate '"NFQUEUE" target Support' | ||
156 | depends on NETFILTER_XTABLES | ||
157 | help | ||
158 | This Target replaced the old obsolete QUEUE target. | ||
159 | |||
160 | As opposed to QUEUE, it supports 65535 different queues, | ||
161 | not just one. | ||
162 | |||
163 | To compile it as a module, choose M here. If unsure, say N. | ||
164 | |||
165 | config NETFILTER_XT_TARGET_NOTRACK | ||
166 | tristate '"NOTRACK" target support' | ||
167 | depends on NETFILTER_XTABLES | ||
168 | depends on IP_NF_RAW || IP6_NF_RAW | ||
169 | depends on IP_NF_CONNTRACK || NF_CONNTRACK | ||
170 | help | ||
171 | The NOTRACK target allows a select rule to specify | ||
172 | which packets *not* to enter the conntrack/NAT | ||
173 | subsystem with all the consequences (no ICMP error tracking, | ||
174 | no protocol helpers for the selected packets). | ||
175 | |||
176 | If you want to compile it as a module, say M here and read | ||
177 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
178 | |||
179 | config NETFILTER_XT_MATCH_COMMENT | ||
180 | tristate '"comment" match support' | ||
181 | depends on NETFILTER_XTABLES | ||
182 | help | ||
183 | This option adds a `comment' dummy-match, which allows you to put | ||
184 | comments in your iptables ruleset. | ||
185 | |||
186 | If you want to compile it as a module, say M here and read | ||
187 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
188 | |||
189 | config NETFILTER_XT_MATCH_CONNBYTES | ||
190 | tristate '"connbytes" per-connection counter match support' | ||
191 | depends on NETFILTER_XTABLES | ||
192 | depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || NF_CT_ACCT | ||
193 | help | ||
194 | This option adds a `connbytes' match, which allows you to match the | ||
195 | number of bytes and/or packets for each direction within a connection. | ||
196 | |||
197 | If you want to compile it as a module, say M here and read | ||
198 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
199 | |||
200 | config NETFILTER_XT_MATCH_CONNMARK | ||
201 | tristate '"connmark" connection mark match support' | ||
202 | depends on NETFILTER_XTABLES | ||
203 | depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || NF_CONNTRACK_MARK | ||
204 | help | ||
205 | This option adds a `connmark' match, which allows you to match the | ||
206 | connection mark value previously set for the session by `CONNMARK'. | ||
207 | |||
208 | If you want to compile it as a module, say M here and read | ||
209 | <file:Documentation/modules.txt>. The module will be called | ||
210 | ipt_connmark.o. If unsure, say `N'. | ||
211 | |||
212 | config NETFILTER_XT_MATCH_CONNTRACK | ||
213 | tristate '"conntrack" connection tracking match support' | ||
214 | depends on NETFILTER_XTABLES | ||
215 | depends on IP_NF_CONNTRACK || NF_CONNTRACK | ||
216 | help | ||
217 | This is a general conntrack match module, a superset of the state match. | ||
218 | |||
219 | It allows matching on additional conntrack information, which is | ||
220 | useful in complex configurations, such as NAT gateways with multiple | ||
221 | internet links or tunnels. | ||
222 | |||
223 | To compile it as a module, choose M here. If unsure, say N. | ||
224 | |||
225 | config NETFILTER_XT_MATCH_DCCP | ||
226 | tristate '"DCCP" protocol match support' | ||
227 | depends on NETFILTER_XTABLES | ||
228 | help | ||
229 | With this option enabled, you will be able to use the iptables | ||
230 | `dccp' match in order to match on DCCP source/destination ports | ||
231 | and DCCP flags. | ||
232 | |||
233 | If you want to compile it as a module, say M here and read | ||
234 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
235 | |||
236 | config NETFILTER_XT_MATCH_HELPER | ||
237 | tristate '"helper" match support' | ||
238 | depends on NETFILTER_XTABLES | ||
239 | depends on IP_NF_CONNTRACK || NF_CONNTRACK | ||
240 | help | ||
241 | Helper matching allows you to match packets in dynamic connections | ||
242 | tracked by a conntrack-helper, ie. ip_conntrack_ftp | ||
243 | |||
244 | To compile it as a module, choose M here. If unsure, say Y. | ||
245 | |||
246 | config NETFILTER_XT_MATCH_LENGTH | ||
247 | tristate '"length" match support' | ||
248 | depends on NETFILTER_XTABLES | ||
249 | help | ||
250 | This option allows you to match the length of a packet against a | ||
251 | specific value or range of values. | ||
252 | |||
253 | To compile it as a module, choose M here. If unsure, say N. | ||
254 | |||
255 | config NETFILTER_XT_MATCH_LIMIT | ||
256 | tristate '"limit" match support' | ||
257 | depends on NETFILTER_XTABLES | ||
258 | help | ||
259 | limit matching allows you to control the rate at which a rule can be | ||
260 | matched: mainly useful in combination with the LOG target ("LOG | ||
261 | target support", below) and to avoid some Denial of Service attacks. | ||
262 | |||
263 | To compile it as a module, choose M here. If unsure, say N. | ||
264 | |||
265 | config NETFILTER_XT_MATCH_MAC | ||
266 | tristate '"mac" address match support' | ||
267 | depends on NETFILTER_XTABLES | ||
268 | help | ||
269 | MAC matching allows you to match packets based on the source | ||
270 | Ethernet address of the packet. | ||
271 | |||
272 | To compile it as a module, choose M here. If unsure, say N. | ||
273 | |||
274 | config NETFILTER_XT_MATCH_MARK | ||
275 | tristate '"mark" match support' | ||
276 | depends on NETFILTER_XTABLES | ||
277 | help | ||
278 | Netfilter mark matching allows you to match packets based on the | ||
279 | `nfmark' value in the packet. This can be set by the MARK target | ||
280 | (see below). | ||
281 | |||
282 | To compile it as a module, choose M here. If unsure, say N. | ||
283 | |||
284 | config NETFILTER_XT_MATCH_PHYSDEV | ||
285 | tristate '"physdev" match support' | ||
286 | depends on NETFILTER_XTABLES && BRIDGE_NETFILTER | ||
287 | help | ||
288 | Physdev packet matching matches against the physical bridge ports | ||
289 | the IP packet arrived on or will leave by. | ||
290 | |||
291 | To compile it as a module, choose M here. If unsure, say N. | ||
292 | |||
293 | config NETFILTER_XT_MATCH_PKTTYPE | ||
294 | tristate '"pkttype" packet type match support' | ||
295 | depends on NETFILTER_XTABLES | ||
296 | help | ||
297 | Packet type matching allows you to match a packet by | ||
298 | its "class", eg. BROADCAST, MULTICAST, ... | ||
299 | |||
300 | Typical usage: | ||
301 | iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG | ||
302 | |||
303 | To compile it as a module, choose M here. If unsure, say N. | ||
304 | |||
305 | config NETFILTER_XT_MATCH_REALM | ||
306 | tristate '"realm" match support' | ||
307 | depends on NETFILTER_XTABLES | ||
308 | select NET_CLS_ROUTE | ||
309 | help | ||
310 | This option adds a `realm' match, which allows you to use the realm | ||
311 | key from the routing subsystem inside iptables. | ||
312 | |||
313 | This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option | ||
314 | in tc world. | ||
315 | |||
316 | If you want to compile it as a module, say M here and read | ||
317 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
318 | |||
319 | config NETFILTER_XT_MATCH_SCTP | ||
320 | tristate '"sctp" protocol match support' | ||
321 | depends on NETFILTER_XTABLES | ||
322 | help | ||
323 | With this option enabled, you will be able to use the | ||
324 | `sctp' match in order to match on SCTP source/destination ports | ||
325 | and SCTP chunk types. | ||
326 | |||
327 | If you want to compile it as a module, say M here and read | ||
328 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
329 | |||
330 | config NETFILTER_XT_MATCH_STATE | ||
331 | tristate '"state" match support' | ||
332 | depends on NETFILTER_XTABLES | ||
333 | depends on IP_NF_CONNTRACK || NF_CONNTRACK | ||
334 | help | ||
335 | Connection state matching allows you to match packets based on their | ||
336 | relationship to a tracked connection (ie. previous packets). This | ||
337 | is a powerful tool for packet classification. | ||
338 | |||
339 | To compile it as a module, choose M here. If unsure, say N. | ||
340 | |||
341 | config NETFILTER_XT_MATCH_STRING | ||
342 | tristate '"string" match support' | ||
343 | depends on NETFILTER_XTABLES | ||
344 | select TEXTSEARCH | ||
345 | select TEXTSEARCH_KMP | ||
346 | select TEXTSEARCH_BM | ||
347 | select TEXTSEARCH_FSM | ||
348 | help | ||
349 | This option adds a `string' match, which allows you to look for | ||
350 | pattern matchings in packets. | ||
351 | |||
352 | To compile it as a module, choose M here. If unsure, say N. | ||
353 | |||
354 | config NETFILTER_XT_MATCH_TCPMSS | ||
355 | tristate '"tcpmss" match support' | ||
356 | depends on NETFILTER_XTABLES | ||
357 | help | ||
358 | This option adds a `tcpmss' match, which allows you to examine the | ||
359 | MSS value of TCP SYN packets, which control the maximum packet size | ||
360 | for that connection. | ||
361 | |||
362 | To compile it as a module, choose M here. If unsure, say N. | ||
363 | |||
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index cb2183145c37..746172ebc91b 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -1,4 +1,5 @@ | |||
1 | netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o | 1 | netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o |
2 | nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o | ||
2 | 3 | ||
3 | obj-$(CONFIG_NETFILTER) = netfilter.o | 4 | obj-$(CONFIG_NETFILTER) = netfilter.o |
4 | 5 | ||
@@ -6,13 +7,43 @@ obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o | |||
6 | obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o | 7 | obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o |
7 | obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o | 8 | obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o |
8 | 9 | ||
9 | nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o | 10 | # connection tracking |
10 | |||
11 | obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o | 11 | obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o |
12 | obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o | ||
13 | 12 | ||
14 | # SCTP protocol connection tracking | 13 | # SCTP protocol connection tracking |
15 | obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o | 14 | obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o |
16 | 15 | ||
17 | # netlink interface for nf_conntrack | 16 | # netlink interface for nf_conntrack |
18 | obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o | 17 | obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o |
18 | |||
19 | # connection tracking helpers | ||
20 | obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o | ||
21 | |||
22 | # generic X tables | ||
23 | obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o | ||
24 | |||
25 | # targets | ||
26 | obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o | ||
27 | obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o | ||
28 | obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o | ||
29 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o | ||
30 | obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o | ||
31 | |||
32 | # matches | ||
33 | obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o | ||
34 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o | ||
35 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o | ||
36 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o | ||
37 | obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o | ||
38 | obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o | ||
39 | obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o | ||
40 | obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o | ||
41 | obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o | ||
42 | obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o | ||
43 | obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o | ||
44 | obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o | ||
45 | obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o | ||
46 | obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o | ||
47 | obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o | ||
48 | obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o | ||
49 | obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o | ||
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index d5a6eaf4a1de..ab0c920f0d30 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c | |||
@@ -545,11 +545,11 @@ static int help(struct sk_buff **pskb, | |||
545 | different IP address. Simply don't record it for | 545 | different IP address. Simply don't record it for |
546 | NAT. */ | 546 | NAT. */ |
547 | if (cmd.l3num == PF_INET) { | 547 | if (cmd.l3num == PF_INET) { |
548 | DEBUGP("conntrack_ftp: NOT RECORDING: %u,%u,%u,%u != %u.%u.%u.%u\n", | 548 | DEBUGP("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT " != " NIPQUAD_FMT "\n", |
549 | NIPQUAD(cmd.u3.ip), | 549 | NIPQUAD(cmd.u3.ip), |
550 | NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip)); | 550 | NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip)); |
551 | } else { | 551 | } else { |
552 | DEBUGP("conntrack_ftp: NOT RECORDING: %x:%x:%x:%x:%x:%x:%x:%x != %x:%x:%x:%x:%x:%x:%x:%x\n", | 552 | DEBUGP("conntrack_ftp: NOT RECORDING: " NIP6_FMT " != " NIP6_FMT "\n", |
553 | NIP6(*((struct in6_addr *)cmd.u3.ip6)), | 553 | NIP6(*((struct in6_addr *)cmd.u3.ip6)), |
554 | NIP6(*((struct in6_addr *)ct->tuplehash[dir] | 554 | NIP6(*((struct in6_addr *)ct->tuplehash[dir] |
555 | .tuple.src.u3.ip6))); | 555 | .tuple.src.u3.ip6))); |
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 3531d142f693..617599aeeead 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
@@ -821,7 +821,7 @@ module_exit(fini); | |||
821 | 821 | ||
822 | /* Some modules need us, but don't depend directly on any symbol. | 822 | /* Some modules need us, but don't depend directly on any symbol. |
823 | They should call this. */ | 823 | They should call this. */ |
824 | void need_nf_conntrack(void) | 824 | void need_conntrack(void) |
825 | { | 825 | { |
826 | } | 826 | } |
827 | 827 | ||
@@ -841,7 +841,7 @@ EXPORT_SYMBOL(nf_conntrack_protocol_unregister); | |||
841 | EXPORT_SYMBOL(nf_ct_invert_tuplepr); | 841 | EXPORT_SYMBOL(nf_ct_invert_tuplepr); |
842 | EXPORT_SYMBOL(nf_conntrack_alter_reply); | 842 | EXPORT_SYMBOL(nf_conntrack_alter_reply); |
843 | EXPORT_SYMBOL(nf_conntrack_destroyed); | 843 | EXPORT_SYMBOL(nf_conntrack_destroyed); |
844 | EXPORT_SYMBOL(need_nf_conntrack); | 844 | EXPORT_SYMBOL(need_conntrack); |
845 | EXPORT_SYMBOL(nf_conntrack_helper_register); | 845 | EXPORT_SYMBOL(nf_conntrack_helper_register); |
846 | EXPORT_SYMBOL(nf_conntrack_helper_unregister); | 846 | EXPORT_SYMBOL(nf_conntrack_helper_unregister); |
847 | EXPORT_SYMBOL(nf_ct_iterate_cleanup); | 847 | EXPORT_SYMBOL(nf_ct_iterate_cleanup); |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c new file mode 100644 index 000000000000..d7817afc6b96 --- /dev/null +++ b/net/netfilter/x_tables.c | |||
@@ -0,0 +1,624 @@ | |||
1 | /* | ||
2 | * x_tables core - Backend for {ip,ip6,arp}_tables | ||
3 | * | ||
4 | * Copyright (C) 2006-2006 Harald Welte <laforge@netfilter.org> | ||
5 | * | ||
6 | * Based on existing ip_tables code which is | ||
7 | * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling | ||
8 | * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/socket.h> | ||
19 | #include <linux/net.h> | ||
20 | #include <linux/proc_fs.h> | ||
21 | #include <linux/seq_file.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/vmalloc.h> | ||
24 | |||
25 | #include <linux/netfilter/x_tables.h> | ||
26 | #include <linux/netfilter_arp.h> | ||
27 | |||
28 | MODULE_LICENSE("GPL"); | ||
29 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | ||
30 | MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module"); | ||
31 | |||
32 | #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) | ||
33 | |||
34 | struct xt_af { | ||
35 | struct semaphore mutex; | ||
36 | struct list_head match; | ||
37 | struct list_head target; | ||
38 | struct list_head tables; | ||
39 | }; | ||
40 | |||
41 | static struct xt_af *xt; | ||
42 | |||
43 | #ifdef DEBUG_IP_FIREWALL_USER | ||
44 | #define duprintf(format, args...) printk(format , ## args) | ||
45 | #else | ||
46 | #define duprintf(format, args...) | ||
47 | #endif | ||
48 | |||
49 | enum { | ||
50 | TABLE, | ||
51 | TARGET, | ||
52 | MATCH, | ||
53 | }; | ||
54 | |||
55 | /* Registration hooks for targets. */ | ||
56 | int | ||
57 | xt_register_target(int af, struct xt_target *target) | ||
58 | { | ||
59 | int ret; | ||
60 | |||
61 | ret = down_interruptible(&xt[af].mutex); | ||
62 | if (ret != 0) | ||
63 | return ret; | ||
64 | list_add(&target->list, &xt[af].target); | ||
65 | up(&xt[af].mutex); | ||
66 | return ret; | ||
67 | } | ||
68 | EXPORT_SYMBOL(xt_register_target); | ||
69 | |||
70 | void | ||
71 | xt_unregister_target(int af, struct xt_target *target) | ||
72 | { | ||
73 | down(&xt[af].mutex); | ||
74 | LIST_DELETE(&xt[af].target, target); | ||
75 | up(&xt[af].mutex); | ||
76 | } | ||
77 | EXPORT_SYMBOL(xt_unregister_target); | ||
78 | |||
79 | int | ||
80 | xt_register_match(int af, struct xt_match *match) | ||
81 | { | ||
82 | int ret; | ||
83 | |||
84 | ret = down_interruptible(&xt[af].mutex); | ||
85 | if (ret != 0) | ||
86 | return ret; | ||
87 | |||
88 | list_add(&match->list, &xt[af].match); | ||
89 | up(&xt[af].mutex); | ||
90 | |||
91 | return ret; | ||
92 | } | ||
93 | EXPORT_SYMBOL(xt_register_match); | ||
94 | |||
95 | void | ||
96 | xt_unregister_match(int af, struct xt_match *match) | ||
97 | { | ||
98 | down(&xt[af].mutex); | ||
99 | LIST_DELETE(&xt[af].match, match); | ||
100 | up(&xt[af].mutex); | ||
101 | } | ||
102 | EXPORT_SYMBOL(xt_unregister_match); | ||
103 | |||
104 | |||
105 | /* | ||
106 | * These are weird, but module loading must not be done with mutex | ||
107 | * held (since they will register), and we have to have a single | ||
108 | * function to use try_then_request_module(). | ||
109 | */ | ||
110 | |||
111 | /* Find match, grabs ref. Returns ERR_PTR() on error. */ | ||
112 | struct xt_match *xt_find_match(int af, const char *name, u8 revision) | ||
113 | { | ||
114 | struct xt_match *m; | ||
115 | int err = 0; | ||
116 | |||
117 | if (down_interruptible(&xt[af].mutex) != 0) | ||
118 | return ERR_PTR(-EINTR); | ||
119 | |||
120 | list_for_each_entry(m, &xt[af].match, list) { | ||
121 | if (strcmp(m->name, name) == 0) { | ||
122 | if (m->revision == revision) { | ||
123 | if (try_module_get(m->me)) { | ||
124 | up(&xt[af].mutex); | ||
125 | return m; | ||
126 | } | ||
127 | } else | ||
128 | err = -EPROTOTYPE; /* Found something. */ | ||
129 | } | ||
130 | } | ||
131 | up(&xt[af].mutex); | ||
132 | return ERR_PTR(err); | ||
133 | } | ||
134 | EXPORT_SYMBOL(xt_find_match); | ||
135 | |||
136 | /* Find target, grabs ref. Returns ERR_PTR() on error. */ | ||
137 | struct xt_target *xt_find_target(int af, const char *name, u8 revision) | ||
138 | { | ||
139 | struct xt_target *t; | ||
140 | int err = 0; | ||
141 | |||
142 | if (down_interruptible(&xt[af].mutex) != 0) | ||
143 | return ERR_PTR(-EINTR); | ||
144 | |||
145 | list_for_each_entry(t, &xt[af].target, list) { | ||
146 | if (strcmp(t->name, name) == 0) { | ||
147 | if (t->revision == revision) { | ||
148 | if (try_module_get(t->me)) { | ||
149 | up(&xt[af].mutex); | ||
150 | return t; | ||
151 | } | ||
152 | } else | ||
153 | err = -EPROTOTYPE; /* Found something. */ | ||
154 | } | ||
155 | } | ||
156 | up(&xt[af].mutex); | ||
157 | return ERR_PTR(err); | ||
158 | } | ||
159 | EXPORT_SYMBOL(xt_find_target); | ||
160 | |||
161 | static const char *xt_prefix[NPROTO] = { | ||
162 | [AF_INET] = "ipt_%s", | ||
163 | [AF_INET6] = "ip6t_%s", | ||
164 | [NF_ARP] = "arpt_%s", | ||
165 | }; | ||
166 | |||
167 | struct xt_target *xt_request_find_target(int af, const char *name, u8 revision) | ||
168 | { | ||
169 | struct xt_target *target; | ||
170 | |||
171 | target = try_then_request_module(xt_find_target(af, name, revision), | ||
172 | xt_prefix[af], name); | ||
173 | if (IS_ERR(target) || !target) | ||
174 | return NULL; | ||
175 | return target; | ||
176 | } | ||
177 | EXPORT_SYMBOL_GPL(xt_request_find_target); | ||
178 | |||
179 | static int match_revfn(int af, const char *name, u8 revision, int *bestp) | ||
180 | { | ||
181 | struct xt_match *m; | ||
182 | int have_rev = 0; | ||
183 | |||
184 | list_for_each_entry(m, &xt[af].match, list) { | ||
185 | if (strcmp(m->name, name) == 0) { | ||
186 | if (m->revision > *bestp) | ||
187 | *bestp = m->revision; | ||
188 | if (m->revision == revision) | ||
189 | have_rev = 1; | ||
190 | } | ||
191 | } | ||
192 | return have_rev; | ||
193 | } | ||
194 | |||
195 | static int target_revfn(int af, const char *name, u8 revision, int *bestp) | ||
196 | { | ||
197 | struct xt_target *t; | ||
198 | int have_rev = 0; | ||
199 | |||
200 | list_for_each_entry(t, &xt[af].target, list) { | ||
201 | if (strcmp(t->name, name) == 0) { | ||
202 | if (t->revision > *bestp) | ||
203 | *bestp = t->revision; | ||
204 | if (t->revision == revision) | ||
205 | have_rev = 1; | ||
206 | } | ||
207 | } | ||
208 | return have_rev; | ||
209 | } | ||
210 | |||
211 | /* Returns true or false (if no such extension at all) */ | ||
212 | int xt_find_revision(int af, const char *name, u8 revision, int target, | ||
213 | int *err) | ||
214 | { | ||
215 | int have_rev, best = -1; | ||
216 | |||
217 | if (down_interruptible(&xt[af].mutex) != 0) { | ||
218 | *err = -EINTR; | ||
219 | return 1; | ||
220 | } | ||
221 | if (target == 1) | ||
222 | have_rev = target_revfn(af, name, revision, &best); | ||
223 | else | ||
224 | have_rev = match_revfn(af, name, revision, &best); | ||
225 | up(&xt[af].mutex); | ||
226 | |||
227 | /* Nothing at all? Return 0 to try loading module. */ | ||
228 | if (best == -1) { | ||
229 | *err = -ENOENT; | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | *err = best; | ||
234 | if (!have_rev) | ||
235 | *err = -EPROTONOSUPPORT; | ||
236 | return 1; | ||
237 | } | ||
238 | EXPORT_SYMBOL_GPL(xt_find_revision); | ||
239 | |||
240 | struct xt_table_info *xt_alloc_table_info(unsigned int size) | ||
241 | { | ||
242 | struct xt_table_info *newinfo; | ||
243 | int cpu; | ||
244 | |||
245 | /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ | ||
246 | if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > num_physpages) | ||
247 | return NULL; | ||
248 | |||
249 | newinfo = kzalloc(sizeof(struct xt_table_info), GFP_KERNEL); | ||
250 | if (!newinfo) | ||
251 | return NULL; | ||
252 | |||
253 | newinfo->size = size; | ||
254 | |||
255 | for_each_cpu(cpu) { | ||
256 | if (size <= PAGE_SIZE) | ||
257 | newinfo->entries[cpu] = kmalloc_node(size, | ||
258 | GFP_KERNEL, | ||
259 | cpu_to_node(cpu)); | ||
260 | else | ||
261 | newinfo->entries[cpu] = vmalloc_node(size, | ||
262 | cpu_to_node(cpu)); | ||
263 | |||
264 | if (newinfo->entries[cpu] == NULL) { | ||
265 | xt_free_table_info(newinfo); | ||
266 | return NULL; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | return newinfo; | ||
271 | } | ||
272 | EXPORT_SYMBOL(xt_alloc_table_info); | ||
273 | |||
274 | void xt_free_table_info(struct xt_table_info *info) | ||
275 | { | ||
276 | int cpu; | ||
277 | |||
278 | for_each_cpu(cpu) { | ||
279 | if (info->size <= PAGE_SIZE) | ||
280 | kfree(info->entries[cpu]); | ||
281 | else | ||
282 | vfree(info->entries[cpu]); | ||
283 | } | ||
284 | kfree(info); | ||
285 | } | ||
286 | EXPORT_SYMBOL(xt_free_table_info); | ||
287 | |||
288 | /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ | ||
289 | struct xt_table *xt_find_table_lock(int af, const char *name) | ||
290 | { | ||
291 | struct xt_table *t; | ||
292 | |||
293 | if (down_interruptible(&xt[af].mutex) != 0) | ||
294 | return ERR_PTR(-EINTR); | ||
295 | |||
296 | list_for_each_entry(t, &xt[af].tables, list) | ||
297 | if (strcmp(t->name, name) == 0 && try_module_get(t->me)) | ||
298 | return t; | ||
299 | up(&xt[af].mutex); | ||
300 | return NULL; | ||
301 | } | ||
302 | EXPORT_SYMBOL_GPL(xt_find_table_lock); | ||
303 | |||
304 | void xt_table_unlock(struct xt_table *table) | ||
305 | { | ||
306 | up(&xt[table->af].mutex); | ||
307 | } | ||
308 | EXPORT_SYMBOL_GPL(xt_table_unlock); | ||
309 | |||
310 | |||
311 | struct xt_table_info * | ||
312 | xt_replace_table(struct xt_table *table, | ||
313 | unsigned int num_counters, | ||
314 | struct xt_table_info *newinfo, | ||
315 | int *error) | ||
316 | { | ||
317 | struct xt_table_info *oldinfo, *private; | ||
318 | |||
319 | /* Do the substitution. */ | ||
320 | write_lock_bh(&table->lock); | ||
321 | private = table->private; | ||
322 | /* Check inside lock: is the old number correct? */ | ||
323 | if (num_counters != private->number) { | ||
324 | duprintf("num_counters != table->private->number (%u/%u)\n", | ||
325 | num_counters, private->number); | ||
326 | write_unlock_bh(&table->lock); | ||
327 | *error = -EAGAIN; | ||
328 | return NULL; | ||
329 | } | ||
330 | oldinfo = private; | ||
331 | table->private = newinfo; | ||
332 | newinfo->initial_entries = oldinfo->initial_entries; | ||
333 | write_unlock_bh(&table->lock); | ||
334 | |||
335 | return oldinfo; | ||
336 | } | ||
337 | EXPORT_SYMBOL_GPL(xt_replace_table); | ||
338 | |||
339 | int xt_register_table(struct xt_table *table, | ||
340 | struct xt_table_info *bootstrap, | ||
341 | struct xt_table_info *newinfo) | ||
342 | { | ||
343 | int ret; | ||
344 | struct xt_table_info *private; | ||
345 | |||
346 | ret = down_interruptible(&xt[table->af].mutex); | ||
347 | if (ret != 0) | ||
348 | return ret; | ||
349 | |||
350 | /* Don't autoload: we'd eat our tail... */ | ||
351 | if (list_named_find(&xt[table->af].tables, table->name)) { | ||
352 | ret = -EEXIST; | ||
353 | goto unlock; | ||
354 | } | ||
355 | |||
356 | /* Simplifies replace_table code. */ | ||
357 | table->private = bootstrap; | ||
358 | if (!xt_replace_table(table, 0, newinfo, &ret)) | ||
359 | goto unlock; | ||
360 | |||
361 | private = table->private; | ||
362 | duprintf("table->private->number = %u\n", private->number); | ||
363 | |||
364 | /* save number of initial entries */ | ||
365 | private->initial_entries = private->number; | ||
366 | |||
367 | rwlock_init(&table->lock); | ||
368 | list_prepend(&xt[table->af].tables, table); | ||
369 | |||
370 | ret = 0; | ||
371 | unlock: | ||
372 | up(&xt[table->af].mutex); | ||
373 | return ret; | ||
374 | } | ||
375 | EXPORT_SYMBOL_GPL(xt_register_table); | ||
376 | |||
377 | void *xt_unregister_table(struct xt_table *table) | ||
378 | { | ||
379 | struct xt_table_info *private; | ||
380 | |||
381 | down(&xt[table->af].mutex); | ||
382 | private = table->private; | ||
383 | LIST_DELETE(&xt[table->af].tables, table); | ||
384 | up(&xt[table->af].mutex); | ||
385 | |||
386 | return private; | ||
387 | } | ||
388 | EXPORT_SYMBOL_GPL(xt_unregister_table); | ||
389 | |||
390 | #ifdef CONFIG_PROC_FS | ||
391 | static char *xt_proto_prefix[NPROTO] = { | ||
392 | [AF_INET] = "ip", | ||
393 | [AF_INET6] = "ip6", | ||
394 | [NF_ARP] = "arp", | ||
395 | }; | ||
396 | |||
397 | static struct list_head *xt_get_idx(struct list_head *list, struct seq_file *seq, loff_t pos) | ||
398 | { | ||
399 | struct list_head *head = list->next; | ||
400 | |||
401 | if (!head || list_empty(list)) | ||
402 | return NULL; | ||
403 | |||
404 | while (pos && (head = head->next)) { | ||
405 | if (head == list) | ||
406 | return NULL; | ||
407 | pos--; | ||
408 | } | ||
409 | return pos ? NULL : head; | ||
410 | } | ||
411 | |||
412 | static struct list_head *type2list(u_int16_t af, u_int16_t type) | ||
413 | { | ||
414 | struct list_head *list; | ||
415 | |||
416 | switch (type) { | ||
417 | case TARGET: | ||
418 | list = &xt[af].target; | ||
419 | break; | ||
420 | case MATCH: | ||
421 | list = &xt[af].match; | ||
422 | break; | ||
423 | case TABLE: | ||
424 | list = &xt[af].tables; | ||
425 | break; | ||
426 | default: | ||
427 | list = NULL; | ||
428 | break; | ||
429 | } | ||
430 | |||
431 | return list; | ||
432 | } | ||
433 | |||
434 | static void *xt_tgt_seq_start(struct seq_file *seq, loff_t *pos) | ||
435 | { | ||
436 | struct proc_dir_entry *pde = (struct proc_dir_entry *) seq->private; | ||
437 | u_int16_t af = (unsigned long)pde->data & 0xffff; | ||
438 | u_int16_t type = (unsigned long)pde->data >> 16; | ||
439 | struct list_head *list; | ||
440 | |||
441 | if (af >= NPROTO) | ||
442 | return NULL; | ||
443 | |||
444 | list = type2list(af, type); | ||
445 | if (!list) | ||
446 | return NULL; | ||
447 | |||
448 | if (down_interruptible(&xt[af].mutex) != 0) | ||
449 | return NULL; | ||
450 | |||
451 | return xt_get_idx(list, seq, *pos); | ||
452 | } | ||
453 | |||
454 | static void *xt_tgt_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
455 | { | ||
456 | struct proc_dir_entry *pde = seq->private; | ||
457 | u_int16_t af = (unsigned long)pde->data & 0xffff; | ||
458 | u_int16_t type = (unsigned long)pde->data >> 16; | ||
459 | struct list_head *list; | ||
460 | |||
461 | if (af >= NPROTO) | ||
462 | return NULL; | ||
463 | |||
464 | list = type2list(af, type); | ||
465 | if (!list) | ||
466 | return NULL; | ||
467 | |||
468 | (*pos)++; | ||
469 | return xt_get_idx(list, seq, *pos); | ||
470 | } | ||
471 | |||
472 | static void xt_tgt_seq_stop(struct seq_file *seq, void *v) | ||
473 | { | ||
474 | struct proc_dir_entry *pde = seq->private; | ||
475 | u_int16_t af = (unsigned long)pde->data & 0xffff; | ||
476 | |||
477 | up(&xt[af].mutex); | ||
478 | } | ||
479 | |||
480 | static int xt_name_seq_show(struct seq_file *seq, void *v) | ||
481 | { | ||
482 | char *name = (char *)v + sizeof(struct list_head); | ||
483 | |||
484 | if (strlen(name)) | ||
485 | return seq_printf(seq, "%s\n", name); | ||
486 | else | ||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static struct seq_operations xt_tgt_seq_ops = { | ||
491 | .start = xt_tgt_seq_start, | ||
492 | .next = xt_tgt_seq_next, | ||
493 | .stop = xt_tgt_seq_stop, | ||
494 | .show = xt_name_seq_show, | ||
495 | }; | ||
496 | |||
497 | static int xt_tgt_open(struct inode *inode, struct file *file) | ||
498 | { | ||
499 | int ret; | ||
500 | |||
501 | ret = seq_open(file, &xt_tgt_seq_ops); | ||
502 | if (!ret) { | ||
503 | struct seq_file *seq = file->private_data; | ||
504 | struct proc_dir_entry *pde = PDE(inode); | ||
505 | |||
506 | seq->private = pde; | ||
507 | } | ||
508 | |||
509 | return ret; | ||
510 | } | ||
511 | |||
512 | static struct file_operations xt_file_ops = { | ||
513 | .owner = THIS_MODULE, | ||
514 | .open = xt_tgt_open, | ||
515 | .read = seq_read, | ||
516 | .llseek = seq_lseek, | ||
517 | .release = seq_release, | ||
518 | }; | ||
519 | |||
520 | #define FORMAT_TABLES "_tables_names" | ||
521 | #define FORMAT_MATCHES "_tables_matches" | ||
522 | #define FORMAT_TARGETS "_tables_targets" | ||
523 | |||
524 | #endif /* CONFIG_PROC_FS */ | ||
525 | |||
526 | int xt_proto_init(int af) | ||
527 | { | ||
528 | #ifdef CONFIG_PROC_FS | ||
529 | char buf[XT_FUNCTION_MAXNAMELEN]; | ||
530 | struct proc_dir_entry *proc; | ||
531 | #endif | ||
532 | |||
533 | if (af >= NPROTO) | ||
534 | return -EINVAL; | ||
535 | |||
536 | |||
537 | #ifdef CONFIG_PROC_FS | ||
538 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
539 | strlcat(buf, FORMAT_TABLES, sizeof(buf)); | ||
540 | proc = proc_net_fops_create(buf, 0440, &xt_file_ops); | ||
541 | if (!proc) | ||
542 | goto out; | ||
543 | proc->data = (void *) ((unsigned long) af | (TABLE << 16)); | ||
544 | |||
545 | |||
546 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
547 | strlcat(buf, FORMAT_MATCHES, sizeof(buf)); | ||
548 | proc = proc_net_fops_create(buf, 0440, &xt_file_ops); | ||
549 | if (!proc) | ||
550 | goto out_remove_tables; | ||
551 | proc->data = (void *) ((unsigned long) af | (MATCH << 16)); | ||
552 | |||
553 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
554 | strlcat(buf, FORMAT_TARGETS, sizeof(buf)); | ||
555 | proc = proc_net_fops_create(buf, 0440, &xt_file_ops); | ||
556 | if (!proc) | ||
557 | goto out_remove_matches; | ||
558 | proc->data = (void *) ((unsigned long) af | (TARGET << 16)); | ||
559 | #endif | ||
560 | |||
561 | return 0; | ||
562 | |||
563 | #ifdef CONFIG_PROC_FS | ||
564 | out_remove_matches: | ||
565 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
566 | strlcat(buf, FORMAT_MATCHES, sizeof(buf)); | ||
567 | proc_net_remove(buf); | ||
568 | |||
569 | out_remove_tables: | ||
570 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
571 | strlcat(buf, FORMAT_TABLES, sizeof(buf)); | ||
572 | proc_net_remove(buf); | ||
573 | out: | ||
574 | return -1; | ||
575 | #endif | ||
576 | } | ||
577 | EXPORT_SYMBOL_GPL(xt_proto_init); | ||
578 | |||
579 | void xt_proto_fini(int af) | ||
580 | { | ||
581 | #ifdef CONFIG_PROC_FS | ||
582 | char buf[XT_FUNCTION_MAXNAMELEN]; | ||
583 | |||
584 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
585 | strlcat(buf, FORMAT_TABLES, sizeof(buf)); | ||
586 | proc_net_remove(buf); | ||
587 | |||
588 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
589 | strlcat(buf, FORMAT_TARGETS, sizeof(buf)); | ||
590 | proc_net_remove(buf); | ||
591 | |||
592 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
593 | strlcat(buf, FORMAT_MATCHES, sizeof(buf)); | ||
594 | proc_net_remove(buf); | ||
595 | #endif /*CONFIG_PROC_FS*/ | ||
596 | } | ||
597 | EXPORT_SYMBOL_GPL(xt_proto_fini); | ||
598 | |||
599 | |||
600 | static int __init xt_init(void) | ||
601 | { | ||
602 | int i; | ||
603 | |||
604 | xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL); | ||
605 | if (!xt) | ||
606 | return -ENOMEM; | ||
607 | |||
608 | for (i = 0; i < NPROTO; i++) { | ||
609 | init_MUTEX(&xt[i].mutex); | ||
610 | INIT_LIST_HEAD(&xt[i].target); | ||
611 | INIT_LIST_HEAD(&xt[i].match); | ||
612 | INIT_LIST_HEAD(&xt[i].tables); | ||
613 | } | ||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | static void __exit xt_fini(void) | ||
618 | { | ||
619 | kfree(xt); | ||
620 | } | ||
621 | |||
622 | module_init(xt_init); | ||
623 | module_exit(xt_fini); | ||
624 | |||
diff --git a/net/ipv4/netfilter/ipt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c index dab78d8bd494..78ee266a12ee 100644 --- a/net/ipv4/netfilter/ipt_CLASSIFY.c +++ b/net/netfilter/xt_CLASSIFY.c | |||
@@ -15,12 +15,13 @@ | |||
15 | #include <linux/ip.h> | 15 | #include <linux/ip.h> |
16 | #include <net/checksum.h> | 16 | #include <net/checksum.h> |
17 | 17 | ||
18 | #include <linux/netfilter_ipv4/ip_tables.h> | 18 | #include <linux/netfilter/x_tables.h> |
19 | #include <linux/netfilter_ipv4/ipt_CLASSIFY.h> | 19 | #include <linux/netfilter/xt_CLASSIFY.h> |
20 | 20 | ||
21 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | 21 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); |
22 | MODULE_LICENSE("GPL"); | 22 | MODULE_LICENSE("GPL"); |
23 | MODULE_DESCRIPTION("iptables qdisc classification target module"); | 23 | MODULE_DESCRIPTION("iptables qdisc classification target module"); |
24 | MODULE_ALIAS("ipt_CLASSIFY"); | ||
24 | 25 | ||
25 | static unsigned int | 26 | static unsigned int |
26 | target(struct sk_buff **pskb, | 27 | target(struct sk_buff **pskb, |
@@ -30,25 +31,25 @@ target(struct sk_buff **pskb, | |||
30 | const void *targinfo, | 31 | const void *targinfo, |
31 | void *userinfo) | 32 | void *userinfo) |
32 | { | 33 | { |
33 | const struct ipt_classify_target_info *clinfo = targinfo; | 34 | const struct xt_classify_target_info *clinfo = targinfo; |
34 | 35 | ||
35 | if((*pskb)->priority != clinfo->priority) | 36 | if ((*pskb)->priority != clinfo->priority) |
36 | (*pskb)->priority = clinfo->priority; | 37 | (*pskb)->priority = clinfo->priority; |
37 | 38 | ||
38 | return IPT_CONTINUE; | 39 | return XT_CONTINUE; |
39 | } | 40 | } |
40 | 41 | ||
41 | static int | 42 | static int |
42 | checkentry(const char *tablename, | 43 | checkentry(const char *tablename, |
43 | const struct ipt_entry *e, | 44 | const void *e, |
44 | void *targinfo, | 45 | void *targinfo, |
45 | unsigned int targinfosize, | 46 | unsigned int targinfosize, |
46 | unsigned int hook_mask) | 47 | unsigned int hook_mask) |
47 | { | 48 | { |
48 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_classify_target_info))){ | 49 | if (targinfosize != XT_ALIGN(sizeof(struct xt_classify_target_info))){ |
49 | printk(KERN_ERR "CLASSIFY: invalid size (%u != %Zu).\n", | 50 | printk(KERN_ERR "CLASSIFY: invalid size (%u != %Zu).\n", |
50 | targinfosize, | 51 | targinfosize, |
51 | IPT_ALIGN(sizeof(struct ipt_classify_target_info))); | 52 | XT_ALIGN(sizeof(struct xt_classify_target_info))); |
52 | return 0; | 53 | return 0; |
53 | } | 54 | } |
54 | 55 | ||
@@ -69,21 +70,39 @@ checkentry(const char *tablename, | |||
69 | return 1; | 70 | return 1; |
70 | } | 71 | } |
71 | 72 | ||
72 | static struct ipt_target ipt_classify_reg = { | 73 | static struct xt_target classify_reg = { |
74 | .name = "CLASSIFY", | ||
75 | .target = target, | ||
76 | .checkentry = checkentry, | ||
77 | .me = THIS_MODULE, | ||
78 | }; | ||
79 | static struct xt_target classify6_reg = { | ||
73 | .name = "CLASSIFY", | 80 | .name = "CLASSIFY", |
74 | .target = target, | 81 | .target = target, |
75 | .checkentry = checkentry, | 82 | .checkentry = checkentry, |
76 | .me = THIS_MODULE, | 83 | .me = THIS_MODULE, |
77 | }; | 84 | }; |
78 | 85 | ||
86 | |||
79 | static int __init init(void) | 87 | static int __init init(void) |
80 | { | 88 | { |
81 | return ipt_register_target(&ipt_classify_reg); | 89 | int ret; |
90 | |||
91 | ret = xt_register_target(AF_INET, &classify_reg); | ||
92 | if (ret) | ||
93 | return ret; | ||
94 | |||
95 | ret = xt_register_target(AF_INET6, &classify6_reg); | ||
96 | if (ret) | ||
97 | xt_unregister_target(AF_INET, &classify_reg); | ||
98 | |||
99 | return ret; | ||
82 | } | 100 | } |
83 | 101 | ||
84 | static void __exit fini(void) | 102 | static void __exit fini(void) |
85 | { | 103 | { |
86 | ipt_unregister_target(&ipt_classify_reg); | 104 | xt_unregister_target(AF_INET, &classify_reg); |
105 | xt_unregister_target(AF_INET6, &classify6_reg); | ||
87 | } | 106 | } |
88 | 107 | ||
89 | module_init(init); | 108 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c index 8acac5a40a92..22506e376be5 100644 --- a/net/ipv4/netfilter/ipt_CONNMARK.c +++ b/net/netfilter/xt_CONNMARK.c | |||
@@ -26,9 +26,10 @@ | |||
26 | MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); | 26 | MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); |
27 | MODULE_DESCRIPTION("IP tables CONNMARK matching module"); | 27 | MODULE_DESCRIPTION("IP tables CONNMARK matching module"); |
28 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
29 | MODULE_ALIAS("ipt_CONNMARK"); | ||
29 | 30 | ||
30 | #include <linux/netfilter_ipv4/ip_tables.h> | 31 | #include <linux/netfilter/x_tables.h> |
31 | #include <linux/netfilter_ipv4/ipt_CONNMARK.h> | 32 | #include <linux/netfilter/xt_CONNMARK.h> |
32 | #include <net/netfilter/nf_conntrack_compat.h> | 33 | #include <net/netfilter/nf_conntrack_compat.h> |
33 | 34 | ||
34 | static unsigned int | 35 | static unsigned int |
@@ -39,7 +40,7 @@ target(struct sk_buff **pskb, | |||
39 | const void *targinfo, | 40 | const void *targinfo, |
40 | void *userinfo) | 41 | void *userinfo) |
41 | { | 42 | { |
42 | const struct ipt_connmark_target_info *markinfo = targinfo; | 43 | const struct xt_connmark_target_info *markinfo = targinfo; |
43 | u_int32_t diff; | 44 | u_int32_t diff; |
44 | u_int32_t nfmark; | 45 | u_int32_t nfmark; |
45 | u_int32_t newmark; | 46 | u_int32_t newmark; |
@@ -48,17 +49,17 @@ target(struct sk_buff **pskb, | |||
48 | 49 | ||
49 | if (ctmark) { | 50 | if (ctmark) { |
50 | switch(markinfo->mode) { | 51 | switch(markinfo->mode) { |
51 | case IPT_CONNMARK_SET: | 52 | case XT_CONNMARK_SET: |
52 | newmark = (*ctmark & ~markinfo->mask) | markinfo->mark; | 53 | newmark = (*ctmark & ~markinfo->mask) | markinfo->mark; |
53 | if (newmark != *ctmark) | 54 | if (newmark != *ctmark) |
54 | *ctmark = newmark; | 55 | *ctmark = newmark; |
55 | break; | 56 | break; |
56 | case IPT_CONNMARK_SAVE: | 57 | case XT_CONNMARK_SAVE: |
57 | newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); | 58 | newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); |
58 | if (*ctmark != newmark) | 59 | if (*ctmark != newmark) |
59 | *ctmark = newmark; | 60 | *ctmark = newmark; |
60 | break; | 61 | break; |
61 | case IPT_CONNMARK_RESTORE: | 62 | case XT_CONNMARK_RESTORE: |
62 | nfmark = (*pskb)->nfmark; | 63 | nfmark = (*pskb)->nfmark; |
63 | diff = (*ctmark ^ nfmark) & markinfo->mask; | 64 | diff = (*ctmark ^ nfmark) & markinfo->mask; |
64 | if (diff != 0) | 65 | if (diff != 0) |
@@ -67,25 +68,25 @@ target(struct sk_buff **pskb, | |||
67 | } | 68 | } |
68 | } | 69 | } |
69 | 70 | ||
70 | return IPT_CONTINUE; | 71 | return XT_CONTINUE; |
71 | } | 72 | } |
72 | 73 | ||
73 | static int | 74 | static int |
74 | checkentry(const char *tablename, | 75 | checkentry(const char *tablename, |
75 | const struct ipt_entry *e, | 76 | const void *entry, |
76 | void *targinfo, | 77 | void *targinfo, |
77 | unsigned int targinfosize, | 78 | unsigned int targinfosize, |
78 | unsigned int hook_mask) | 79 | unsigned int hook_mask) |
79 | { | 80 | { |
80 | struct ipt_connmark_target_info *matchinfo = targinfo; | 81 | struct xt_connmark_target_info *matchinfo = targinfo; |
81 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) { | 82 | if (targinfosize != XT_ALIGN(sizeof(struct xt_connmark_target_info))) { |
82 | printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n", | 83 | printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n", |
83 | targinfosize, | 84 | targinfosize, |
84 | IPT_ALIGN(sizeof(struct ipt_connmark_target_info))); | 85 | XT_ALIGN(sizeof(struct xt_connmark_target_info))); |
85 | return 0; | 86 | return 0; |
86 | } | 87 | } |
87 | 88 | ||
88 | if (matchinfo->mode == IPT_CONNMARK_RESTORE) { | 89 | if (matchinfo->mode == XT_CONNMARK_RESTORE) { |
89 | if (strcmp(tablename, "mangle") != 0) { | 90 | if (strcmp(tablename, "mangle") != 0) { |
90 | printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename); | 91 | printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename); |
91 | return 0; | 92 | return 0; |
@@ -100,7 +101,13 @@ checkentry(const char *tablename, | |||
100 | return 1; | 101 | return 1; |
101 | } | 102 | } |
102 | 103 | ||
103 | static struct ipt_target ipt_connmark_reg = { | 104 | static struct xt_target connmark_reg = { |
105 | .name = "CONNMARK", | ||
106 | .target = &target, | ||
107 | .checkentry = &checkentry, | ||
108 | .me = THIS_MODULE | ||
109 | }; | ||
110 | static struct xt_target connmark6_reg = { | ||
104 | .name = "CONNMARK", | 111 | .name = "CONNMARK", |
105 | .target = &target, | 112 | .target = &target, |
106 | .checkentry = &checkentry, | 113 | .checkentry = &checkentry, |
@@ -109,13 +116,25 @@ static struct ipt_target ipt_connmark_reg = { | |||
109 | 116 | ||
110 | static int __init init(void) | 117 | static int __init init(void) |
111 | { | 118 | { |
112 | need_ip_conntrack(); | 119 | int ret; |
113 | return ipt_register_target(&ipt_connmark_reg); | 120 | |
121 | need_conntrack(); | ||
122 | |||
123 | ret = xt_register_target(AF_INET, &connmark_reg); | ||
124 | if (ret) | ||
125 | return ret; | ||
126 | |||
127 | ret = xt_register_target(AF_INET6, &connmark6_reg); | ||
128 | if (ret) | ||
129 | xt_unregister_target(AF_INET, &connmark_reg); | ||
130 | |||
131 | return ret; | ||
114 | } | 132 | } |
115 | 133 | ||
116 | static void __exit fini(void) | 134 | static void __exit fini(void) |
117 | { | 135 | { |
118 | ipt_unregister_target(&ipt_connmark_reg); | 136 | xt_unregister_target(AF_INET, &connmark_reg); |
137 | xt_unregister_target(AF_INET6, &connmark6_reg); | ||
119 | } | 138 | } |
120 | 139 | ||
121 | module_init(init); | 140 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_MARK.c b/net/netfilter/xt_MARK.c index 52b4f2c296bf..0c11ee9550f3 100644 --- a/net/ipv4/netfilter/ipt_MARK.c +++ b/net/netfilter/xt_MARK.c | |||
@@ -12,12 +12,14 @@ | |||
12 | #include <linux/ip.h> | 12 | #include <linux/ip.h> |
13 | #include <net/checksum.h> | 13 | #include <net/checksum.h> |
14 | 14 | ||
15 | #include <linux/netfilter_ipv4/ip_tables.h> | 15 | #include <linux/netfilter/x_tables.h> |
16 | #include <linux/netfilter_ipv4/ipt_MARK.h> | 16 | #include <linux/netfilter/xt_MARK.h> |
17 | 17 | ||
18 | MODULE_LICENSE("GPL"); | 18 | MODULE_LICENSE("GPL"); |
19 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | 19 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); |
20 | MODULE_DESCRIPTION("iptables MARK modification module"); | 20 | MODULE_DESCRIPTION("ip[6]tables MARK modification module"); |
21 | MODULE_ALIAS("ipt_MARK"); | ||
22 | MODULE_ALIAS("ip6t_MARK"); | ||
21 | 23 | ||
22 | static unsigned int | 24 | static unsigned int |
23 | target_v0(struct sk_buff **pskb, | 25 | target_v0(struct sk_buff **pskb, |
@@ -27,12 +29,12 @@ target_v0(struct sk_buff **pskb, | |||
27 | const void *targinfo, | 29 | const void *targinfo, |
28 | void *userinfo) | 30 | void *userinfo) |
29 | { | 31 | { |
30 | const struct ipt_mark_target_info *markinfo = targinfo; | 32 | const struct xt_mark_target_info *markinfo = targinfo; |
31 | 33 | ||
32 | if((*pskb)->nfmark != markinfo->mark) | 34 | if((*pskb)->nfmark != markinfo->mark) |
33 | (*pskb)->nfmark = markinfo->mark; | 35 | (*pskb)->nfmark = markinfo->mark; |
34 | 36 | ||
35 | return IPT_CONTINUE; | 37 | return XT_CONTINUE; |
36 | } | 38 | } |
37 | 39 | ||
38 | static unsigned int | 40 | static unsigned int |
@@ -43,19 +45,19 @@ target_v1(struct sk_buff **pskb, | |||
43 | const void *targinfo, | 45 | const void *targinfo, |
44 | void *userinfo) | 46 | void *userinfo) |
45 | { | 47 | { |
46 | const struct ipt_mark_target_info_v1 *markinfo = targinfo; | 48 | const struct xt_mark_target_info_v1 *markinfo = targinfo; |
47 | int mark = 0; | 49 | int mark = 0; |
48 | 50 | ||
49 | switch (markinfo->mode) { | 51 | switch (markinfo->mode) { |
50 | case IPT_MARK_SET: | 52 | case XT_MARK_SET: |
51 | mark = markinfo->mark; | 53 | mark = markinfo->mark; |
52 | break; | 54 | break; |
53 | 55 | ||
54 | case IPT_MARK_AND: | 56 | case XT_MARK_AND: |
55 | mark = (*pskb)->nfmark & markinfo->mark; | 57 | mark = (*pskb)->nfmark & markinfo->mark; |
56 | break; | 58 | break; |
57 | 59 | ||
58 | case IPT_MARK_OR: | 60 | case XT_MARK_OR: |
59 | mark = (*pskb)->nfmark | markinfo->mark; | 61 | mark = (*pskb)->nfmark | markinfo->mark; |
60 | break; | 62 | break; |
61 | } | 63 | } |
@@ -63,23 +65,23 @@ target_v1(struct sk_buff **pskb, | |||
63 | if((*pskb)->nfmark != mark) | 65 | if((*pskb)->nfmark != mark) |
64 | (*pskb)->nfmark = mark; | 66 | (*pskb)->nfmark = mark; |
65 | 67 | ||
66 | return IPT_CONTINUE; | 68 | return XT_CONTINUE; |
67 | } | 69 | } |
68 | 70 | ||
69 | 71 | ||
70 | static int | 72 | static int |
71 | checkentry_v0(const char *tablename, | 73 | checkentry_v0(const char *tablename, |
72 | const struct ipt_entry *e, | 74 | const void *entry, |
73 | void *targinfo, | 75 | void *targinfo, |
74 | unsigned int targinfosize, | 76 | unsigned int targinfosize, |
75 | unsigned int hook_mask) | 77 | unsigned int hook_mask) |
76 | { | 78 | { |
77 | struct ipt_mark_target_info *markinfo = targinfo; | 79 | struct xt_mark_target_info *markinfo = targinfo; |
78 | 80 | ||
79 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) { | 81 | if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info))) { |
80 | printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", | 82 | printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", |
81 | targinfosize, | 83 | targinfosize, |
82 | IPT_ALIGN(sizeof(struct ipt_mark_target_info))); | 84 | XT_ALIGN(sizeof(struct xt_mark_target_info))); |
83 | return 0; | 85 | return 0; |
84 | } | 86 | } |
85 | 87 | ||
@@ -98,17 +100,17 @@ checkentry_v0(const char *tablename, | |||
98 | 100 | ||
99 | static int | 101 | static int |
100 | checkentry_v1(const char *tablename, | 102 | checkentry_v1(const char *tablename, |
101 | const struct ipt_entry *e, | 103 | const void *entry, |
102 | void *targinfo, | 104 | void *targinfo, |
103 | unsigned int targinfosize, | 105 | unsigned int targinfosize, |
104 | unsigned int hook_mask) | 106 | unsigned int hook_mask) |
105 | { | 107 | { |
106 | struct ipt_mark_target_info_v1 *markinfo = targinfo; | 108 | struct xt_mark_target_info_v1 *markinfo = targinfo; |
107 | 109 | ||
108 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))){ | 110 | if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info_v1))){ |
109 | printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", | 111 | printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", |
110 | targinfosize, | 112 | targinfosize, |
111 | IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))); | 113 | XT_ALIGN(sizeof(struct xt_mark_target_info_v1))); |
112 | return 0; | 114 | return 0; |
113 | } | 115 | } |
114 | 116 | ||
@@ -117,9 +119,9 @@ checkentry_v1(const char *tablename, | |||
117 | return 0; | 119 | return 0; |
118 | } | 120 | } |
119 | 121 | ||
120 | if (markinfo->mode != IPT_MARK_SET | 122 | if (markinfo->mode != XT_MARK_SET |
121 | && markinfo->mode != IPT_MARK_AND | 123 | && markinfo->mode != XT_MARK_AND |
122 | && markinfo->mode != IPT_MARK_OR) { | 124 | && markinfo->mode != XT_MARK_OR) { |
123 | printk(KERN_WARNING "MARK: unknown mode %u\n", | 125 | printk(KERN_WARNING "MARK: unknown mode %u\n", |
124 | markinfo->mode); | 126 | markinfo->mode); |
125 | return 0; | 127 | return 0; |
@@ -133,7 +135,7 @@ checkentry_v1(const char *tablename, | |||
133 | return 1; | 135 | return 1; |
134 | } | 136 | } |
135 | 137 | ||
136 | static struct ipt_target ipt_mark_reg_v0 = { | 138 | static struct xt_target ipt_mark_reg_v0 = { |
137 | .name = "MARK", | 139 | .name = "MARK", |
138 | .target = target_v0, | 140 | .target = target_v0, |
139 | .checkentry = checkentry_v0, | 141 | .checkentry = checkentry_v0, |
@@ -141,7 +143,7 @@ static struct ipt_target ipt_mark_reg_v0 = { | |||
141 | .revision = 0, | 143 | .revision = 0, |
142 | }; | 144 | }; |
143 | 145 | ||
144 | static struct ipt_target ipt_mark_reg_v1 = { | 146 | static struct xt_target ipt_mark_reg_v1 = { |
145 | .name = "MARK", | 147 | .name = "MARK", |
146 | .target = target_v1, | 148 | .target = target_v1, |
147 | .checkentry = checkentry_v1, | 149 | .checkentry = checkentry_v1, |
@@ -149,23 +151,40 @@ static struct ipt_target ipt_mark_reg_v1 = { | |||
149 | .revision = 1, | 151 | .revision = 1, |
150 | }; | 152 | }; |
151 | 153 | ||
154 | static struct xt_target ip6t_mark_reg_v0 = { | ||
155 | .name = "MARK", | ||
156 | .target = target_v0, | ||
157 | .checkentry = checkentry_v0, | ||
158 | .me = THIS_MODULE, | ||
159 | .revision = 0, | ||
160 | }; | ||
161 | |||
152 | static int __init init(void) | 162 | static int __init init(void) |
153 | { | 163 | { |
154 | int err; | 164 | int err; |
155 | 165 | ||
156 | err = ipt_register_target(&ipt_mark_reg_v0); | 166 | err = xt_register_target(AF_INET, &ipt_mark_reg_v0); |
157 | if (!err) { | 167 | if (err) |
158 | err = ipt_register_target(&ipt_mark_reg_v1); | 168 | return err; |
159 | if (err) | 169 | |
160 | ipt_unregister_target(&ipt_mark_reg_v0); | 170 | err = xt_register_target(AF_INET, &ipt_mark_reg_v1); |
171 | if (err) | ||
172 | xt_unregister_target(AF_INET, &ipt_mark_reg_v0); | ||
173 | |||
174 | err = xt_register_target(AF_INET6, &ip6t_mark_reg_v0); | ||
175 | if (err) { | ||
176 | xt_unregister_target(AF_INET, &ipt_mark_reg_v0); | ||
177 | xt_unregister_target(AF_INET, &ipt_mark_reg_v1); | ||
161 | } | 178 | } |
179 | |||
162 | return err; | 180 | return err; |
163 | } | 181 | } |
164 | 182 | ||
165 | static void __exit fini(void) | 183 | static void __exit fini(void) |
166 | { | 184 | { |
167 | ipt_unregister_target(&ipt_mark_reg_v0); | 185 | xt_unregister_target(AF_INET, &ipt_mark_reg_v0); |
168 | ipt_unregister_target(&ipt_mark_reg_v1); | 186 | xt_unregister_target(AF_INET, &ipt_mark_reg_v1); |
187 | xt_unregister_target(AF_INET6, &ip6t_mark_reg_v0); | ||
169 | } | 188 | } |
170 | 189 | ||
171 | module_init(init); | 190 | module_init(init); |
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c new file mode 100644 index 000000000000..8b76b6f8d1e4 --- /dev/null +++ b/net/netfilter/xt_NFQUEUE.c | |||
@@ -0,0 +1,107 @@ | |||
1 | /* iptables module for using new netfilter netlink queue | ||
2 | * | ||
3 | * (C) 2005 by Harald Welte <laforge@netfilter.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | |||
14 | #include <linux/netfilter.h> | ||
15 | #include <linux/netfilter_arp.h> | ||
16 | #include <linux/netfilter/x_tables.h> | ||
17 | #include <linux/netfilter/xt_NFQUEUE.h> | ||
18 | |||
19 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | ||
20 | MODULE_DESCRIPTION("[ip,ip6,arp]_tables NFQUEUE target"); | ||
21 | MODULE_LICENSE("GPL"); | ||
22 | MODULE_ALIAS("ipt_NFQUEUE"); | ||
23 | MODULE_ALIAS("ip6t_NFQUEUE"); | ||
24 | MODULE_ALIAS("arpt_NFQUEUE"); | ||
25 | |||
26 | static unsigned int | ||
27 | target(struct sk_buff **pskb, | ||
28 | const struct net_device *in, | ||
29 | const struct net_device *out, | ||
30 | unsigned int hooknum, | ||
31 | const void *targinfo, | ||
32 | void *userinfo) | ||
33 | { | ||
34 | const struct xt_NFQ_info *tinfo = targinfo; | ||
35 | |||
36 | return NF_QUEUE_NR(tinfo->queuenum); | ||
37 | } | ||
38 | |||
39 | static int | ||
40 | checkentry(const char *tablename, | ||
41 | const void *entry, | ||
42 | void *targinfo, | ||
43 | unsigned int targinfosize, | ||
44 | unsigned int hook_mask) | ||
45 | { | ||
46 | if (targinfosize != XT_ALIGN(sizeof(struct xt_NFQ_info))) { | ||
47 | printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n", | ||
48 | targinfosize, | ||
49 | XT_ALIGN(sizeof(struct xt_NFQ_info))); | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | return 1; | ||
54 | } | ||
55 | |||
56 | static struct xt_target ipt_NFQ_reg = { | ||
57 | .name = "NFQUEUE", | ||
58 | .target = target, | ||
59 | .checkentry = checkentry, | ||
60 | .me = THIS_MODULE, | ||
61 | }; | ||
62 | |||
63 | static struct xt_target ip6t_NFQ_reg = { | ||
64 | .name = "NFQUEUE", | ||
65 | .target = target, | ||
66 | .checkentry = checkentry, | ||
67 | .me = THIS_MODULE, | ||
68 | }; | ||
69 | |||
70 | static struct xt_target arpt_NFQ_reg = { | ||
71 | .name = "NFQUEUE", | ||
72 | .target = target, | ||
73 | .checkentry = checkentry, | ||
74 | .me = THIS_MODULE, | ||
75 | }; | ||
76 | |||
77 | static int __init init(void) | ||
78 | { | ||
79 | int ret; | ||
80 | ret = xt_register_target(AF_INET, &ipt_NFQ_reg); | ||
81 | if (ret) | ||
82 | return ret; | ||
83 | ret = xt_register_target(AF_INET6, &ip6t_NFQ_reg); | ||
84 | if (ret) | ||
85 | goto out_ip; | ||
86 | ret = xt_register_target(NF_ARP, &arpt_NFQ_reg); | ||
87 | if (ret) | ||
88 | goto out_ip6; | ||
89 | |||
90 | return ret; | ||
91 | out_ip6: | ||
92 | xt_unregister_target(AF_INET6, &ip6t_NFQ_reg); | ||
93 | out_ip: | ||
94 | xt_unregister_target(AF_INET, &ipt_NFQ_reg); | ||
95 | |||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | static void __exit fini(void) | ||
100 | { | ||
101 | xt_unregister_target(NF_ARP, &arpt_NFQ_reg); | ||
102 | xt_unregister_target(AF_INET6, &ip6t_NFQ_reg); | ||
103 | xt_unregister_target(AF_INET, &ipt_NFQ_reg); | ||
104 | } | ||
105 | |||
106 | module_init(init); | ||
107 | module_exit(fini); | ||
diff --git a/net/ipv4/netfilter/ipt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c index e3c69d072c6e..24d477afa939 100644 --- a/net/ipv4/netfilter/ipt_NOTRACK.c +++ b/net/netfilter/xt_NOTRACK.c | |||
@@ -4,9 +4,12 @@ | |||
4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
5 | #include <linux/skbuff.h> | 5 | #include <linux/skbuff.h> |
6 | 6 | ||
7 | #include <linux/netfilter_ipv4/ip_tables.h> | 7 | #include <linux/netfilter/x_tables.h> |
8 | #include <net/netfilter/nf_conntrack_compat.h> | 8 | #include <net/netfilter/nf_conntrack_compat.h> |
9 | 9 | ||
10 | MODULE_LICENSE("GPL"); | ||
11 | MODULE_ALIAS("ipt_NOTRACK"); | ||
12 | |||
10 | static unsigned int | 13 | static unsigned int |
11 | target(struct sk_buff **pskb, | 14 | target(struct sk_buff **pskb, |
12 | const struct net_device *in, | 15 | const struct net_device *in, |
@@ -17,7 +20,7 @@ target(struct sk_buff **pskb, | |||
17 | { | 20 | { |
18 | /* Previously seen (loopback)? Ignore. */ | 21 | /* Previously seen (loopback)? Ignore. */ |
19 | if ((*pskb)->nfct != NULL) | 22 | if ((*pskb)->nfct != NULL) |
20 | return IPT_CONTINUE; | 23 | return XT_CONTINUE; |
21 | 24 | ||
22 | /* Attach fake conntrack entry. | 25 | /* Attach fake conntrack entry. |
23 | If there is a real ct entry correspondig to this packet, | 26 | If there is a real ct entry correspondig to this packet, |
@@ -27,12 +30,12 @@ target(struct sk_buff **pskb, | |||
27 | (*pskb)->nfctinfo = IP_CT_NEW; | 30 | (*pskb)->nfctinfo = IP_CT_NEW; |
28 | nf_conntrack_get((*pskb)->nfct); | 31 | nf_conntrack_get((*pskb)->nfct); |
29 | 32 | ||
30 | return IPT_CONTINUE; | 33 | return XT_CONTINUE; |
31 | } | 34 | } |
32 | 35 | ||
33 | static int | 36 | static int |
34 | checkentry(const char *tablename, | 37 | checkentry(const char *tablename, |
35 | const struct ipt_entry *e, | 38 | const void *entry, |
36 | void *targinfo, | 39 | void *targinfo, |
37 | unsigned int targinfosize, | 40 | unsigned int targinfosize, |
38 | unsigned int hook_mask) | 41 | unsigned int hook_mask) |
@@ -51,26 +54,39 @@ checkentry(const char *tablename, | |||
51 | return 1; | 54 | return 1; |
52 | } | 55 | } |
53 | 56 | ||
54 | static struct ipt_target ipt_notrack_reg = { | 57 | static struct xt_target notrack_reg = { |
55 | .name = "NOTRACK", | 58 | .name = "NOTRACK", |
56 | .target = target, | 59 | .target = target, |
57 | .checkentry = checkentry, | 60 | .checkentry = checkentry, |
58 | .me = THIS_MODULE | 61 | .me = THIS_MODULE, |
62 | }; | ||
63 | static struct xt_target notrack6_reg = { | ||
64 | .name = "NOTRACK", | ||
65 | .target = target, | ||
66 | .checkentry = checkentry, | ||
67 | .me = THIS_MODULE, | ||
59 | }; | 68 | }; |
60 | 69 | ||
61 | static int __init init(void) | 70 | static int __init init(void) |
62 | { | 71 | { |
63 | if (ipt_register_target(&ipt_notrack_reg)) | 72 | int ret; |
64 | return -EINVAL; | 73 | |
74 | ret = xt_register_target(AF_INET, ¬rack_reg); | ||
75 | if (ret) | ||
76 | return ret; | ||
65 | 77 | ||
66 | return 0; | 78 | ret = xt_register_target(AF_INET6, ¬rack6_reg); |
79 | if (ret) | ||
80 | xt_unregister_target(AF_INET, ¬rack_reg); | ||
81 | |||
82 | return ret; | ||
67 | } | 83 | } |
68 | 84 | ||
69 | static void __exit fini(void) | 85 | static void __exit fini(void) |
70 | { | 86 | { |
71 | ipt_unregister_target(&ipt_notrack_reg); | 87 | xt_unregister_target(AF_INET6, ¬rack6_reg); |
88 | xt_unregister_target(AF_INET, ¬rack_reg); | ||
72 | } | 89 | } |
73 | 90 | ||
74 | module_init(init); | 91 | module_init(init); |
75 | module_exit(fini); | 92 | module_exit(fini); |
76 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/ipv4/netfilter/ipt_comment.c b/net/netfilter/xt_comment.c index 6b76a1ea5245..4ba6fd65c6e9 100644 --- a/net/ipv4/netfilter/ipt_comment.c +++ b/net/netfilter/xt_comment.c | |||
@@ -6,12 +6,14 @@ | |||
6 | 6 | ||
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | #include <linux/skbuff.h> | 8 | #include <linux/skbuff.h> |
9 | #include <linux/netfilter_ipv4/ip_tables.h> | 9 | #include <linux/netfilter/x_tables.h> |
10 | #include <linux/netfilter_ipv4/ipt_comment.h> | 10 | #include <linux/netfilter/xt_comment.h> |
11 | 11 | ||
12 | MODULE_AUTHOR("Brad Fisher <brad@info-link.net>"); | 12 | MODULE_AUTHOR("Brad Fisher <brad@info-link.net>"); |
13 | MODULE_DESCRIPTION("iptables comment match module"); | 13 | MODULE_DESCRIPTION("iptables comment match module"); |
14 | MODULE_LICENSE("GPL"); | 14 | MODULE_LICENSE("GPL"); |
15 | MODULE_ALIAS("ipt_comment"); | ||
16 | MODULE_ALIAS("ip6t_comment"); | ||
15 | 17 | ||
16 | static int | 18 | static int |
17 | match(const struct sk_buff *skb, | 19 | match(const struct sk_buff *skb, |
@@ -19,6 +21,7 @@ match(const struct sk_buff *skb, | |||
19 | const struct net_device *out, | 21 | const struct net_device *out, |
20 | const void *matchinfo, | 22 | const void *matchinfo, |
21 | int offset, | 23 | int offset, |
24 | unsigned int protooff, | ||
22 | int *hotdrop) | 25 | int *hotdrop) |
23 | { | 26 | { |
24 | /* We always match */ | 27 | /* We always match */ |
@@ -27,18 +30,25 @@ match(const struct sk_buff *skb, | |||
27 | 30 | ||
28 | static int | 31 | static int |
29 | checkentry(const char *tablename, | 32 | checkentry(const char *tablename, |
30 | const struct ipt_ip *ip, | 33 | const void *ip, |
31 | void *matchinfo, | 34 | void *matchinfo, |
32 | unsigned int matchsize, | 35 | unsigned int matchsize, |
33 | unsigned int hook_mask) | 36 | unsigned int hook_mask) |
34 | { | 37 | { |
35 | /* Check the size */ | 38 | /* Check the size */ |
36 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_comment_info))) | 39 | if (matchsize != XT_ALIGN(sizeof(struct xt_comment_info))) |
37 | return 0; | 40 | return 0; |
38 | return 1; | 41 | return 1; |
39 | } | 42 | } |
40 | 43 | ||
41 | static struct ipt_match comment_match = { | 44 | static struct xt_match comment_match = { |
45 | .name = "comment", | ||
46 | .match = match, | ||
47 | .checkentry = checkentry, | ||
48 | .me = THIS_MODULE | ||
49 | }; | ||
50 | |||
51 | static struct xt_match comment6_match = { | ||
42 | .name = "comment", | 52 | .name = "comment", |
43 | .match = match, | 53 | .match = match, |
44 | .checkentry = checkentry, | 54 | .checkentry = checkentry, |
@@ -47,12 +57,23 @@ static struct ipt_match comment_match = { | |||
47 | 57 | ||
48 | static int __init init(void) | 58 | static int __init init(void) |
49 | { | 59 | { |
50 | return ipt_register_match(&comment_match); | 60 | int ret; |
61 | |||
62 | ret = xt_register_match(AF_INET, &comment_match); | ||
63 | if (ret) | ||
64 | return ret; | ||
65 | |||
66 | ret = xt_register_match(AF_INET6, &comment6_match); | ||
67 | if (ret) | ||
68 | xt_unregister_match(AF_INET, &comment_match); | ||
69 | |||
70 | return ret; | ||
51 | } | 71 | } |
52 | 72 | ||
53 | static void __exit fini(void) | 73 | static void __exit fini(void) |
54 | { | 74 | { |
55 | ipt_unregister_match(&comment_match); | 75 | xt_unregister_match(AF_INET, &comment_match); |
76 | xt_unregister_match(AF_INET6, &comment6_match); | ||
56 | } | 77 | } |
57 | 78 | ||
58 | module_init(init); | 79 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_connbytes.c b/net/netfilter/xt_connbytes.c index d68a048b7176..150d2a4b0f71 100644 --- a/net/ipv4/netfilter/ipt_connbytes.c +++ b/net/netfilter/xt_connbytes.c | |||
@@ -6,13 +6,15 @@ | |||
6 | * - add functionality to match number of packets | 6 | * - add functionality to match number of packets |
7 | * - add functionality to match average packet size | 7 | * - add functionality to match average packet size |
8 | * - add support to match directions seperately | 8 | * - add support to match directions seperately |
9 | * 2005-10-16 Harald Welte <laforge@netfilter.org> | ||
10 | * - Port to x_tables | ||
9 | * | 11 | * |
10 | */ | 12 | */ |
11 | #include <linux/module.h> | 13 | #include <linux/module.h> |
12 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
13 | #include <net/netfilter/nf_conntrack_compat.h> | 15 | #include <net/netfilter/nf_conntrack_compat.h> |
14 | #include <linux/netfilter_ipv4/ip_tables.h> | 16 | #include <linux/netfilter/x_tables.h> |
15 | #include <linux/netfilter_ipv4/ipt_connbytes.h> | 17 | #include <linux/netfilter/xt_connbytes.h> |
16 | 18 | ||
17 | #include <asm/div64.h> | 19 | #include <asm/div64.h> |
18 | #include <asm/bitops.h> | 20 | #include <asm/bitops.h> |
@@ -20,6 +22,7 @@ | |||
20 | MODULE_LICENSE("GPL"); | 22 | MODULE_LICENSE("GPL"); |
21 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | 23 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); |
22 | MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection"); | 24 | MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection"); |
25 | MODULE_ALIAS("ipt_connbytes"); | ||
23 | 26 | ||
24 | /* 64bit divisor, dividend and result. dynamic precision */ | 27 | /* 64bit divisor, dividend and result. dynamic precision */ |
25 | static u_int64_t div64_64(u_int64_t dividend, u_int64_t divisor) | 28 | static u_int64_t div64_64(u_int64_t dividend, u_int64_t divisor) |
@@ -43,9 +46,10 @@ match(const struct sk_buff *skb, | |||
43 | const struct net_device *out, | 46 | const struct net_device *out, |
44 | const void *matchinfo, | 47 | const void *matchinfo, |
45 | int offset, | 48 | int offset, |
49 | unsigned int protoff, | ||
46 | int *hotdrop) | 50 | int *hotdrop) |
47 | { | 51 | { |
48 | const struct ipt_connbytes_info *sinfo = matchinfo; | 52 | const struct xt_connbytes_info *sinfo = matchinfo; |
49 | u_int64_t what = 0; /* initialize to make gcc happy */ | 53 | u_int64_t what = 0; /* initialize to make gcc happy */ |
50 | const struct ip_conntrack_counter *counters; | 54 | const struct ip_conntrack_counter *counters; |
51 | 55 | ||
@@ -53,45 +57,45 @@ match(const struct sk_buff *skb, | |||
53 | return 0; /* no match */ | 57 | return 0; /* no match */ |
54 | 58 | ||
55 | switch (sinfo->what) { | 59 | switch (sinfo->what) { |
56 | case IPT_CONNBYTES_PKTS: | 60 | case XT_CONNBYTES_PKTS: |
57 | switch (sinfo->direction) { | 61 | switch (sinfo->direction) { |
58 | case IPT_CONNBYTES_DIR_ORIGINAL: | 62 | case XT_CONNBYTES_DIR_ORIGINAL: |
59 | what = counters[IP_CT_DIR_ORIGINAL].packets; | 63 | what = counters[IP_CT_DIR_ORIGINAL].packets; |
60 | break; | 64 | break; |
61 | case IPT_CONNBYTES_DIR_REPLY: | 65 | case XT_CONNBYTES_DIR_REPLY: |
62 | what = counters[IP_CT_DIR_REPLY].packets; | 66 | what = counters[IP_CT_DIR_REPLY].packets; |
63 | break; | 67 | break; |
64 | case IPT_CONNBYTES_DIR_BOTH: | 68 | case XT_CONNBYTES_DIR_BOTH: |
65 | what = counters[IP_CT_DIR_ORIGINAL].packets; | 69 | what = counters[IP_CT_DIR_ORIGINAL].packets; |
66 | what += counters[IP_CT_DIR_REPLY].packets; | 70 | what += counters[IP_CT_DIR_REPLY].packets; |
67 | break; | 71 | break; |
68 | } | 72 | } |
69 | break; | 73 | break; |
70 | case IPT_CONNBYTES_BYTES: | 74 | case XT_CONNBYTES_BYTES: |
71 | switch (sinfo->direction) { | 75 | switch (sinfo->direction) { |
72 | case IPT_CONNBYTES_DIR_ORIGINAL: | 76 | case XT_CONNBYTES_DIR_ORIGINAL: |
73 | what = counters[IP_CT_DIR_ORIGINAL].bytes; | 77 | what = counters[IP_CT_DIR_ORIGINAL].bytes; |
74 | break; | 78 | break; |
75 | case IPT_CONNBYTES_DIR_REPLY: | 79 | case XT_CONNBYTES_DIR_REPLY: |
76 | what = counters[IP_CT_DIR_REPLY].bytes; | 80 | what = counters[IP_CT_DIR_REPLY].bytes; |
77 | break; | 81 | break; |
78 | case IPT_CONNBYTES_DIR_BOTH: | 82 | case XT_CONNBYTES_DIR_BOTH: |
79 | what = counters[IP_CT_DIR_ORIGINAL].bytes; | 83 | what = counters[IP_CT_DIR_ORIGINAL].bytes; |
80 | what += counters[IP_CT_DIR_REPLY].bytes; | 84 | what += counters[IP_CT_DIR_REPLY].bytes; |
81 | break; | 85 | break; |
82 | } | 86 | } |
83 | break; | 87 | break; |
84 | case IPT_CONNBYTES_AVGPKT: | 88 | case XT_CONNBYTES_AVGPKT: |
85 | switch (sinfo->direction) { | 89 | switch (sinfo->direction) { |
86 | case IPT_CONNBYTES_DIR_ORIGINAL: | 90 | case XT_CONNBYTES_DIR_ORIGINAL: |
87 | what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes, | 91 | what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes, |
88 | counters[IP_CT_DIR_ORIGINAL].packets); | 92 | counters[IP_CT_DIR_ORIGINAL].packets); |
89 | break; | 93 | break; |
90 | case IPT_CONNBYTES_DIR_REPLY: | 94 | case XT_CONNBYTES_DIR_REPLY: |
91 | what = div64_64(counters[IP_CT_DIR_REPLY].bytes, | 95 | what = div64_64(counters[IP_CT_DIR_REPLY].bytes, |
92 | counters[IP_CT_DIR_REPLY].packets); | 96 | counters[IP_CT_DIR_REPLY].packets); |
93 | break; | 97 | break; |
94 | case IPT_CONNBYTES_DIR_BOTH: | 98 | case XT_CONNBYTES_DIR_BOTH: |
95 | { | 99 | { |
96 | u_int64_t bytes; | 100 | u_int64_t bytes; |
97 | u_int64_t pkts; | 101 | u_int64_t pkts; |
@@ -117,30 +121,36 @@ match(const struct sk_buff *skb, | |||
117 | } | 121 | } |
118 | 122 | ||
119 | static int check(const char *tablename, | 123 | static int check(const char *tablename, |
120 | const struct ipt_ip *ip, | 124 | const void *ip, |
121 | void *matchinfo, | 125 | void *matchinfo, |
122 | unsigned int matchsize, | 126 | unsigned int matchsize, |
123 | unsigned int hook_mask) | 127 | unsigned int hook_mask) |
124 | { | 128 | { |
125 | const struct ipt_connbytes_info *sinfo = matchinfo; | 129 | const struct xt_connbytes_info *sinfo = matchinfo; |
126 | 130 | ||
127 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_connbytes_info))) | 131 | if (matchsize != XT_ALIGN(sizeof(struct xt_connbytes_info))) |
128 | return 0; | 132 | return 0; |
129 | 133 | ||
130 | if (sinfo->what != IPT_CONNBYTES_PKTS && | 134 | if (sinfo->what != XT_CONNBYTES_PKTS && |
131 | sinfo->what != IPT_CONNBYTES_BYTES && | 135 | sinfo->what != XT_CONNBYTES_BYTES && |
132 | sinfo->what != IPT_CONNBYTES_AVGPKT) | 136 | sinfo->what != XT_CONNBYTES_AVGPKT) |
133 | return 0; | 137 | return 0; |
134 | 138 | ||
135 | if (sinfo->direction != IPT_CONNBYTES_DIR_ORIGINAL && | 139 | if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL && |
136 | sinfo->direction != IPT_CONNBYTES_DIR_REPLY && | 140 | sinfo->direction != XT_CONNBYTES_DIR_REPLY && |
137 | sinfo->direction != IPT_CONNBYTES_DIR_BOTH) | 141 | sinfo->direction != XT_CONNBYTES_DIR_BOTH) |
138 | return 0; | 142 | return 0; |
139 | 143 | ||
140 | return 1; | 144 | return 1; |
141 | } | 145 | } |
142 | 146 | ||
143 | static struct ipt_match state_match = { | 147 | static struct xt_match connbytes_match = { |
148 | .name = "connbytes", | ||
149 | .match = &match, | ||
150 | .checkentry = &check, | ||
151 | .me = THIS_MODULE | ||
152 | }; | ||
153 | static struct xt_match connbytes6_match = { | ||
144 | .name = "connbytes", | 154 | .name = "connbytes", |
145 | .match = &match, | 155 | .match = &match, |
146 | .checkentry = &check, | 156 | .checkentry = &check, |
@@ -149,12 +159,21 @@ static struct ipt_match state_match = { | |||
149 | 159 | ||
150 | static int __init init(void) | 160 | static int __init init(void) |
151 | { | 161 | { |
152 | return ipt_register_match(&state_match); | 162 | int ret; |
163 | ret = xt_register_match(AF_INET, &connbytes_match); | ||
164 | if (ret) | ||
165 | return ret; | ||
166 | |||
167 | ret = xt_register_match(AF_INET6, &connbytes6_match); | ||
168 | if (ret) | ||
169 | xt_unregister_match(AF_INET, &connbytes_match); | ||
170 | return ret; | ||
153 | } | 171 | } |
154 | 172 | ||
155 | static void __exit fini(void) | 173 | static void __exit fini(void) |
156 | { | 174 | { |
157 | ipt_unregister_match(&state_match); | 175 | xt_unregister_match(AF_INET, &connbytes_match); |
176 | xt_unregister_match(AF_INET6, &connbytes6_match); | ||
158 | } | 177 | } |
159 | 178 | ||
160 | module_init(init); | 179 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_connmark.c b/net/netfilter/xt_connmark.c index 5306ef293b92..d06e925032da 100644 --- a/net/ipv4/netfilter/ipt_connmark.c +++ b/net/netfilter/xt_connmark.c | |||
@@ -25,9 +25,10 @@ | |||
25 | MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); | 25 | MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); |
26 | MODULE_DESCRIPTION("IP tables connmark match module"); | 26 | MODULE_DESCRIPTION("IP tables connmark match module"); |
27 | MODULE_LICENSE("GPL"); | 27 | MODULE_LICENSE("GPL"); |
28 | MODULE_ALIAS("ipt_connmark"); | ||
28 | 29 | ||
29 | #include <linux/netfilter_ipv4/ip_tables.h> | 30 | #include <linux/netfilter/x_tables.h> |
30 | #include <linux/netfilter_ipv4/ipt_connmark.h> | 31 | #include <linux/netfilter/xt_connmark.h> |
31 | #include <net/netfilter/nf_conntrack_compat.h> | 32 | #include <net/netfilter/nf_conntrack_compat.h> |
32 | 33 | ||
33 | static int | 34 | static int |
@@ -36,9 +37,10 @@ match(const struct sk_buff *skb, | |||
36 | const struct net_device *out, | 37 | const struct net_device *out, |
37 | const void *matchinfo, | 38 | const void *matchinfo, |
38 | int offset, | 39 | int offset, |
40 | unsigned int protoff, | ||
39 | int *hotdrop) | 41 | int *hotdrop) |
40 | { | 42 | { |
41 | const struct ipt_connmark_info *info = matchinfo; | 43 | const struct xt_connmark_info *info = matchinfo; |
42 | u_int32_t ctinfo; | 44 | u_int32_t ctinfo; |
43 | const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo); | 45 | const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo); |
44 | if (!ctmark) | 46 | if (!ctmark) |
@@ -49,14 +51,14 @@ match(const struct sk_buff *skb, | |||
49 | 51 | ||
50 | static int | 52 | static int |
51 | checkentry(const char *tablename, | 53 | checkentry(const char *tablename, |
52 | const struct ipt_ip *ip, | 54 | const void *ip, |
53 | void *matchinfo, | 55 | void *matchinfo, |
54 | unsigned int matchsize, | 56 | unsigned int matchsize, |
55 | unsigned int hook_mask) | 57 | unsigned int hook_mask) |
56 | { | 58 | { |
57 | struct ipt_connmark_info *cm = | 59 | struct xt_connmark_info *cm = |
58 | (struct ipt_connmark_info *)matchinfo; | 60 | (struct xt_connmark_info *)matchinfo; |
59 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info))) | 61 | if (matchsize != XT_ALIGN(sizeof(struct xt_connmark_info))) |
60 | return 0; | 62 | return 0; |
61 | 63 | ||
62 | if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { | 64 | if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { |
@@ -67,21 +69,40 @@ checkentry(const char *tablename, | |||
67 | return 1; | 69 | return 1; |
68 | } | 70 | } |
69 | 71 | ||
70 | static struct ipt_match connmark_match = { | 72 | static struct xt_match connmark_match = { |
73 | .name = "connmark", | ||
74 | .match = &match, | ||
75 | .checkentry = &checkentry, | ||
76 | .me = THIS_MODULE | ||
77 | }; | ||
78 | static struct xt_match connmark6_match = { | ||
71 | .name = "connmark", | 79 | .name = "connmark", |
72 | .match = &match, | 80 | .match = &match, |
73 | .checkentry = &checkentry, | 81 | .checkentry = &checkentry, |
74 | .me = THIS_MODULE | 82 | .me = THIS_MODULE |
75 | }; | 83 | }; |
76 | 84 | ||
85 | |||
77 | static int __init init(void) | 86 | static int __init init(void) |
78 | { | 87 | { |
79 | return ipt_register_match(&connmark_match); | 88 | int ret; |
89 | |||
90 | need_conntrack(); | ||
91 | |||
92 | ret = xt_register_match(AF_INET, &connmark_match); | ||
93 | if (ret) | ||
94 | return ret; | ||
95 | |||
96 | ret = xt_register_match(AF_INET6, &connmark6_match); | ||
97 | if (ret) | ||
98 | xt_unregister_match(AF_INET, &connmark_match); | ||
99 | return ret; | ||
80 | } | 100 | } |
81 | 101 | ||
82 | static void __exit fini(void) | 102 | static void __exit fini(void) |
83 | { | 103 | { |
84 | ipt_unregister_match(&connmark_match); | 104 | xt_unregister_match(AF_INET6, &connmark6_match); |
105 | xt_unregister_match(AF_INET, &connmark_match); | ||
85 | } | 106 | } |
86 | 107 | ||
87 | module_init(init); | 108 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_conntrack.c b/net/netfilter/xt_conntrack.c index c8d18705469b..ffdebc95eb95 100644 --- a/net/ipv4/netfilter/ipt_conntrack.c +++ b/net/netfilter/xt_conntrack.c | |||
@@ -18,12 +18,13 @@ | |||
18 | #include <net/netfilter/nf_conntrack.h> | 18 | #include <net/netfilter/nf_conntrack.h> |
19 | #endif | 19 | #endif |
20 | 20 | ||
21 | #include <linux/netfilter_ipv4/ip_tables.h> | 21 | #include <linux/netfilter/x_tables.h> |
22 | #include <linux/netfilter_ipv4/ipt_conntrack.h> | 22 | #include <linux/netfilter/xt_conntrack.h> |
23 | 23 | ||
24 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
25 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | 25 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); |
26 | MODULE_DESCRIPTION("iptables connection tracking match module"); | 26 | MODULE_DESCRIPTION("iptables connection tracking match module"); |
27 | MODULE_ALIAS("ipt_conntrack"); | ||
27 | 28 | ||
28 | #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) | 29 | #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) |
29 | 30 | ||
@@ -33,9 +34,10 @@ match(const struct sk_buff *skb, | |||
33 | const struct net_device *out, | 34 | const struct net_device *out, |
34 | const void *matchinfo, | 35 | const void *matchinfo, |
35 | int offset, | 36 | int offset, |
37 | unsigned int protoff, | ||
36 | int *hotdrop) | 38 | int *hotdrop) |
37 | { | 39 | { |
38 | const struct ipt_conntrack_info *sinfo = matchinfo; | 40 | const struct xt_conntrack_info *sinfo = matchinfo; |
39 | struct ip_conntrack *ct; | 41 | struct ip_conntrack *ct; |
40 | enum ip_conntrack_info ctinfo; | 42 | enum ip_conntrack_info ctinfo; |
41 | unsigned int statebit; | 43 | unsigned int statebit; |
@@ -45,58 +47,58 @@ match(const struct sk_buff *skb, | |||
45 | #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) | 47 | #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) |
46 | 48 | ||
47 | if (ct == &ip_conntrack_untracked) | 49 | if (ct == &ip_conntrack_untracked) |
48 | statebit = IPT_CONNTRACK_STATE_UNTRACKED; | 50 | statebit = XT_CONNTRACK_STATE_UNTRACKED; |
49 | else if (ct) | 51 | else if (ct) |
50 | statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); | 52 | statebit = XT_CONNTRACK_STATE_BIT(ctinfo); |
51 | else | 53 | else |
52 | statebit = IPT_CONNTRACK_STATE_INVALID; | 54 | statebit = XT_CONNTRACK_STATE_INVALID; |
53 | 55 | ||
54 | if(sinfo->flags & IPT_CONNTRACK_STATE) { | 56 | if(sinfo->flags & XT_CONNTRACK_STATE) { |
55 | if (ct) { | 57 | if (ct) { |
56 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip != | 58 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip != |
57 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) | 59 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) |
58 | statebit |= IPT_CONNTRACK_STATE_SNAT; | 60 | statebit |= XT_CONNTRACK_STATE_SNAT; |
59 | 61 | ||
60 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip != | 62 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip != |
61 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip) | 63 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip) |
62 | statebit |= IPT_CONNTRACK_STATE_DNAT; | 64 | statebit |= XT_CONNTRACK_STATE_DNAT; |
63 | } | 65 | } |
64 | 66 | ||
65 | if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE)) | 67 | if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE)) |
66 | return 0; | 68 | return 0; |
67 | } | 69 | } |
68 | 70 | ||
69 | if(sinfo->flags & IPT_CONNTRACK_PROTO) { | 71 | if(sinfo->flags & XT_CONNTRACK_PROTO) { |
70 | if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) | 72 | if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO)) |
71 | return 0; | 73 | return 0; |
72 | } | 74 | } |
73 | 75 | ||
74 | if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { | 76 | if(sinfo->flags & XT_CONNTRACK_ORIGSRC) { |
75 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) | 77 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC)) |
76 | return 0; | 78 | return 0; |
77 | } | 79 | } |
78 | 80 | ||
79 | if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { | 81 | if(sinfo->flags & XT_CONNTRACK_ORIGDST) { |
80 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) | 82 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST)) |
81 | return 0; | 83 | return 0; |
82 | } | 84 | } |
83 | 85 | ||
84 | if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { | 86 | if(sinfo->flags & XT_CONNTRACK_REPLSRC) { |
85 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) | 87 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC)) |
86 | return 0; | 88 | return 0; |
87 | } | 89 | } |
88 | 90 | ||
89 | if(sinfo->flags & IPT_CONNTRACK_REPLDST) { | 91 | if(sinfo->flags & XT_CONNTRACK_REPLDST) { |
90 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) | 92 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST)) |
91 | return 0; | 93 | return 0; |
92 | } | 94 | } |
93 | 95 | ||
94 | if(sinfo->flags & IPT_CONNTRACK_STATUS) { | 96 | if(sinfo->flags & XT_CONNTRACK_STATUS) { |
95 | if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) | 97 | if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS)) |
96 | return 0; | 98 | return 0; |
97 | } | 99 | } |
98 | 100 | ||
99 | if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { | 101 | if(sinfo->flags & XT_CONNTRACK_EXPIRES) { |
100 | unsigned long expires; | 102 | unsigned long expires; |
101 | 103 | ||
102 | if(!ct) | 104 | if(!ct) |
@@ -104,7 +106,7 @@ match(const struct sk_buff *skb, | |||
104 | 106 | ||
105 | expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; | 107 | expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; |
106 | 108 | ||
107 | if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) | 109 | if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES)) |
108 | return 0; | 110 | return 0; |
109 | } | 111 | } |
110 | 112 | ||
@@ -118,9 +120,10 @@ match(const struct sk_buff *skb, | |||
118 | const struct net_device *out, | 120 | const struct net_device *out, |
119 | const void *matchinfo, | 121 | const void *matchinfo, |
120 | int offset, | 122 | int offset, |
123 | unsigned int protoff, | ||
121 | int *hotdrop) | 124 | int *hotdrop) |
122 | { | 125 | { |
123 | const struct ipt_conntrack_info *sinfo = matchinfo; | 126 | const struct xt_conntrack_info *sinfo = matchinfo; |
124 | struct nf_conn *ct; | 127 | struct nf_conn *ct; |
125 | enum ip_conntrack_info ctinfo; | 128 | enum ip_conntrack_info ctinfo; |
126 | unsigned int statebit; | 129 | unsigned int statebit; |
@@ -130,58 +133,58 @@ match(const struct sk_buff *skb, | |||
130 | #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) | 133 | #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) |
131 | 134 | ||
132 | if (ct == &nf_conntrack_untracked) | 135 | if (ct == &nf_conntrack_untracked) |
133 | statebit = IPT_CONNTRACK_STATE_UNTRACKED; | 136 | statebit = XT_CONNTRACK_STATE_UNTRACKED; |
134 | else if (ct) | 137 | else if (ct) |
135 | statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); | 138 | statebit = XT_CONNTRACK_STATE_BIT(ctinfo); |
136 | else | 139 | else |
137 | statebit = IPT_CONNTRACK_STATE_INVALID; | 140 | statebit = XT_CONNTRACK_STATE_INVALID; |
138 | 141 | ||
139 | if(sinfo->flags & IPT_CONNTRACK_STATE) { | 142 | if(sinfo->flags & XT_CONNTRACK_STATE) { |
140 | if (ct) { | 143 | if (ct) { |
141 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip != | 144 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip != |
142 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip) | 145 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip) |
143 | statebit |= IPT_CONNTRACK_STATE_SNAT; | 146 | statebit |= XT_CONNTRACK_STATE_SNAT; |
144 | 147 | ||
145 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip != | 148 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip != |
146 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip) | 149 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip) |
147 | statebit |= IPT_CONNTRACK_STATE_DNAT; | 150 | statebit |= XT_CONNTRACK_STATE_DNAT; |
148 | } | 151 | } |
149 | 152 | ||
150 | if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE)) | 153 | if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE)) |
151 | return 0; | 154 | return 0; |
152 | } | 155 | } |
153 | 156 | ||
154 | if(sinfo->flags & IPT_CONNTRACK_PROTO) { | 157 | if(sinfo->flags & XT_CONNTRACK_PROTO) { |
155 | if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) | 158 | if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO)) |
156 | return 0; | 159 | return 0; |
157 | } | 160 | } |
158 | 161 | ||
159 | if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { | 162 | if(sinfo->flags & XT_CONNTRACK_ORIGSRC) { |
160 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) | 163 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC)) |
161 | return 0; | 164 | return 0; |
162 | } | 165 | } |
163 | 166 | ||
164 | if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { | 167 | if(sinfo->flags & XT_CONNTRACK_ORIGDST) { |
165 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) | 168 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST)) |
166 | return 0; | 169 | return 0; |
167 | } | 170 | } |
168 | 171 | ||
169 | if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { | 172 | if(sinfo->flags & XT_CONNTRACK_REPLSRC) { |
170 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) | 173 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC)) |
171 | return 0; | 174 | return 0; |
172 | } | 175 | } |
173 | 176 | ||
174 | if(sinfo->flags & IPT_CONNTRACK_REPLDST) { | 177 | if(sinfo->flags & XT_CONNTRACK_REPLDST) { |
175 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) | 178 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST)) |
176 | return 0; | 179 | return 0; |
177 | } | 180 | } |
178 | 181 | ||
179 | if(sinfo->flags & IPT_CONNTRACK_STATUS) { | 182 | if(sinfo->flags & XT_CONNTRACK_STATUS) { |
180 | if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) | 183 | if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS)) |
181 | return 0; | 184 | return 0; |
182 | } | 185 | } |
183 | 186 | ||
184 | if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { | 187 | if(sinfo->flags & XT_CONNTRACK_EXPIRES) { |
185 | unsigned long expires; | 188 | unsigned long expires; |
186 | 189 | ||
187 | if(!ct) | 190 | if(!ct) |
@@ -189,7 +192,7 @@ match(const struct sk_buff *skb, | |||
189 | 192 | ||
190 | expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; | 193 | expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; |
191 | 194 | ||
192 | if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) | 195 | if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES)) |
193 | return 0; | 196 | return 0; |
194 | } | 197 | } |
195 | 198 | ||
@@ -199,18 +202,18 @@ match(const struct sk_buff *skb, | |||
199 | #endif /* CONFIG_NF_IP_CONNTRACK */ | 202 | #endif /* CONFIG_NF_IP_CONNTRACK */ |
200 | 203 | ||
201 | static int check(const char *tablename, | 204 | static int check(const char *tablename, |
202 | const struct ipt_ip *ip, | 205 | const void *ip, |
203 | void *matchinfo, | 206 | void *matchinfo, |
204 | unsigned int matchsize, | 207 | unsigned int matchsize, |
205 | unsigned int hook_mask) | 208 | unsigned int hook_mask) |
206 | { | 209 | { |
207 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_conntrack_info))) | 210 | if (matchsize != XT_ALIGN(sizeof(struct xt_conntrack_info))) |
208 | return 0; | 211 | return 0; |
209 | 212 | ||
210 | return 1; | 213 | return 1; |
211 | } | 214 | } |
212 | 215 | ||
213 | static struct ipt_match conntrack_match = { | 216 | static struct xt_match conntrack_match = { |
214 | .name = "conntrack", | 217 | .name = "conntrack", |
215 | .match = &match, | 218 | .match = &match, |
216 | .checkentry = &check, | 219 | .checkentry = &check, |
@@ -219,13 +222,16 @@ static struct ipt_match conntrack_match = { | |||
219 | 222 | ||
220 | static int __init init(void) | 223 | static int __init init(void) |
221 | { | 224 | { |
222 | need_ip_conntrack(); | 225 | int ret; |
223 | return ipt_register_match(&conntrack_match); | 226 | need_conntrack(); |
227 | ret = xt_register_match(AF_INET, &conntrack_match); | ||
228 | |||
229 | return ret; | ||
224 | } | 230 | } |
225 | 231 | ||
226 | static void __exit fini(void) | 232 | static void __exit fini(void) |
227 | { | 233 | { |
228 | ipt_unregister_match(&conntrack_match); | 234 | xt_unregister_match(AF_INET, &conntrack_match); |
229 | } | 235 | } |
230 | 236 | ||
231 | module_init(init); | 237 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_dccp.c b/net/netfilter/xt_dccp.c index ad3278bba6c1..779f42fc9524 100644 --- a/net/ipv4/netfilter/ipt_dccp.c +++ b/net/netfilter/xt_dccp.c | |||
@@ -14,8 +14,16 @@ | |||
14 | #include <net/ip.h> | 14 | #include <net/ip.h> |
15 | #include <linux/dccp.h> | 15 | #include <linux/dccp.h> |
16 | 16 | ||
17 | #include <linux/netfilter/x_tables.h> | ||
18 | #include <linux/netfilter/xt_dccp.h> | ||
19 | |||
17 | #include <linux/netfilter_ipv4/ip_tables.h> | 20 | #include <linux/netfilter_ipv4/ip_tables.h> |
18 | #include <linux/netfilter_ipv4/ipt_dccp.h> | 21 | #include <linux/netfilter_ipv6/ip6_tables.h> |
22 | |||
23 | MODULE_LICENSE("GPL"); | ||
24 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | ||
25 | MODULE_DESCRIPTION("Match for DCCP protocol packets"); | ||
26 | MODULE_ALIAS("ipt_dccp"); | ||
19 | 27 | ||
20 | #define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \ | 28 | #define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \ |
21 | || (!!((invflag) & (option)) ^ (cond))) | 29 | || (!!((invflag) & (option)) ^ (cond))) |
@@ -26,6 +34,7 @@ static DEFINE_SPINLOCK(dccp_buflock); | |||
26 | static inline int | 34 | static inline int |
27 | dccp_find_option(u_int8_t option, | 35 | dccp_find_option(u_int8_t option, |
28 | const struct sk_buff *skb, | 36 | const struct sk_buff *skb, |
37 | unsigned int protoff, | ||
29 | const struct dccp_hdr *dh, | 38 | const struct dccp_hdr *dh, |
30 | int *hotdrop) | 39 | int *hotdrop) |
31 | { | 40 | { |
@@ -44,9 +53,7 @@ dccp_find_option(u_int8_t option, | |||
44 | return 0; | 53 | return 0; |
45 | 54 | ||
46 | spin_lock_bh(&dccp_buflock); | 55 | spin_lock_bh(&dccp_buflock); |
47 | op = skb_header_pointer(skb, | 56 | op = skb_header_pointer(skb, protoff + optoff, optlen, dccp_optbuf); |
48 | skb->nh.iph->ihl*4 + optoff, | ||
49 | optlen, dccp_optbuf); | ||
50 | if (op == NULL) { | 57 | if (op == NULL) { |
51 | /* If we don't have the whole header, drop packet. */ | 58 | /* If we don't have the whole header, drop packet. */ |
52 | spin_unlock_bh(&dccp_buflock); | 59 | spin_unlock_bh(&dccp_buflock); |
@@ -78,10 +85,10 @@ match_types(const struct dccp_hdr *dh, u_int16_t typemask) | |||
78 | } | 85 | } |
79 | 86 | ||
80 | static inline int | 87 | static inline int |
81 | match_option(u_int8_t option, const struct sk_buff *skb, | 88 | match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff, |
82 | const struct dccp_hdr *dh, int *hotdrop) | 89 | const struct dccp_hdr *dh, int *hotdrop) |
83 | { | 90 | { |
84 | return dccp_find_option(option, skb, dh, hotdrop); | 91 | return dccp_find_option(option, skb, protoff, dh, hotdrop); |
85 | } | 92 | } |
86 | 93 | ||
87 | static int | 94 | static int |
@@ -90,16 +97,17 @@ match(const struct sk_buff *skb, | |||
90 | const struct net_device *out, | 97 | const struct net_device *out, |
91 | const void *matchinfo, | 98 | const void *matchinfo, |
92 | int offset, | 99 | int offset, |
100 | unsigned int protoff, | ||
93 | int *hotdrop) | 101 | int *hotdrop) |
94 | { | 102 | { |
95 | const struct ipt_dccp_info *info = | 103 | const struct xt_dccp_info *info = |
96 | (const struct ipt_dccp_info *)matchinfo; | 104 | (const struct xt_dccp_info *)matchinfo; |
97 | struct dccp_hdr _dh, *dh; | 105 | struct dccp_hdr _dh, *dh; |
98 | 106 | ||
99 | if (offset) | 107 | if (offset) |
100 | return 0; | 108 | return 0; |
101 | 109 | ||
102 | dh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_dh), &_dh); | 110 | dh = skb_header_pointer(skb, protoff, sizeof(_dh), &_dh); |
103 | if (dh == NULL) { | 111 | if (dh == NULL) { |
104 | *hotdrop = 1; | 112 | *hotdrop = 1; |
105 | return 0; | 113 | return 0; |
@@ -107,42 +115,73 @@ match(const struct sk_buff *skb, | |||
107 | 115 | ||
108 | return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0]) | 116 | return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0]) |
109 | && (ntohs(dh->dccph_sport) <= info->spts[1])), | 117 | && (ntohs(dh->dccph_sport) <= info->spts[1])), |
110 | IPT_DCCP_SRC_PORTS, info->flags, info->invflags) | 118 | XT_DCCP_SRC_PORTS, info->flags, info->invflags) |
111 | && DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0]) | 119 | && DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0]) |
112 | && (ntohs(dh->dccph_dport) <= info->dpts[1])), | 120 | && (ntohs(dh->dccph_dport) <= info->dpts[1])), |
113 | IPT_DCCP_DEST_PORTS, info->flags, info->invflags) | 121 | XT_DCCP_DEST_PORTS, info->flags, info->invflags) |
114 | && DCCHECK(match_types(dh, info->typemask), | 122 | && DCCHECK(match_types(dh, info->typemask), |
115 | IPT_DCCP_TYPE, info->flags, info->invflags) | 123 | XT_DCCP_TYPE, info->flags, info->invflags) |
116 | && DCCHECK(match_option(info->option, skb, dh, hotdrop), | 124 | && DCCHECK(match_option(info->option, skb, protoff, dh, |
117 | IPT_DCCP_OPTION, info->flags, info->invflags); | 125 | hotdrop), |
126 | XT_DCCP_OPTION, info->flags, info->invflags); | ||
118 | } | 127 | } |
119 | 128 | ||
120 | static int | 129 | static int |
121 | checkentry(const char *tablename, | 130 | checkentry(const char *tablename, |
122 | const struct ipt_ip *ip, | 131 | const void *inf, |
123 | void *matchinfo, | 132 | void *matchinfo, |
124 | unsigned int matchsize, | 133 | unsigned int matchsize, |
125 | unsigned int hook_mask) | 134 | unsigned int hook_mask) |
126 | { | 135 | { |
127 | const struct ipt_dccp_info *info; | 136 | const struct ipt_ip *ip = inf; |
137 | const struct xt_dccp_info *info; | ||
128 | 138 | ||
129 | info = (const struct ipt_dccp_info *)matchinfo; | 139 | info = (const struct xt_dccp_info *)matchinfo; |
130 | 140 | ||
131 | return ip->proto == IPPROTO_DCCP | 141 | return ip->proto == IPPROTO_DCCP |
132 | && !(ip->invflags & IPT_INV_PROTO) | 142 | && !(ip->invflags & XT_INV_PROTO) |
133 | && matchsize == IPT_ALIGN(sizeof(struct ipt_dccp_info)) | 143 | && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info)) |
134 | && !(info->flags & ~IPT_DCCP_VALID_FLAGS) | 144 | && !(info->flags & ~XT_DCCP_VALID_FLAGS) |
135 | && !(info->invflags & ~IPT_DCCP_VALID_FLAGS) | 145 | && !(info->invflags & ~XT_DCCP_VALID_FLAGS) |
136 | && !(info->invflags & ~info->flags); | 146 | && !(info->invflags & ~info->flags); |
137 | } | 147 | } |
138 | 148 | ||
139 | static struct ipt_match dccp_match = | 149 | static int |
150 | checkentry6(const char *tablename, | ||
151 | const void *inf, | ||
152 | void *matchinfo, | ||
153 | unsigned int matchsize, | ||
154 | unsigned int hook_mask) | ||
155 | { | ||
156 | const struct ip6t_ip6 *ip = inf; | ||
157 | const struct xt_dccp_info *info; | ||
158 | |||
159 | info = (const struct xt_dccp_info *)matchinfo; | ||
160 | |||
161 | return ip->proto == IPPROTO_DCCP | ||
162 | && !(ip->invflags & XT_INV_PROTO) | ||
163 | && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info)) | ||
164 | && !(info->flags & ~XT_DCCP_VALID_FLAGS) | ||
165 | && !(info->invflags & ~XT_DCCP_VALID_FLAGS) | ||
166 | && !(info->invflags & ~info->flags); | ||
167 | } | ||
168 | |||
169 | |||
170 | static struct xt_match dccp_match = | ||
140 | { | 171 | { |
141 | .name = "dccp", | 172 | .name = "dccp", |
142 | .match = &match, | 173 | .match = &match, |
143 | .checkentry = &checkentry, | 174 | .checkentry = &checkentry, |
144 | .me = THIS_MODULE, | 175 | .me = THIS_MODULE, |
145 | }; | 176 | }; |
177 | static struct xt_match dccp6_match = | ||
178 | { | ||
179 | .name = "dccp", | ||
180 | .match = &match, | ||
181 | .checkentry = &checkentry6, | ||
182 | .me = THIS_MODULE, | ||
183 | }; | ||
184 | |||
146 | 185 | ||
147 | static int __init init(void) | 186 | static int __init init(void) |
148 | { | 187 | { |
@@ -154,23 +193,29 @@ static int __init init(void) | |||
154 | dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL); | 193 | dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL); |
155 | if (!dccp_optbuf) | 194 | if (!dccp_optbuf) |
156 | return -ENOMEM; | 195 | return -ENOMEM; |
157 | ret = ipt_register_match(&dccp_match); | 196 | ret = xt_register_match(AF_INET, &dccp_match); |
158 | if (ret) | 197 | if (ret) |
159 | kfree(dccp_optbuf); | 198 | goto out_kfree; |
199 | ret = xt_register_match(AF_INET6, &dccp6_match); | ||
200 | if (ret) | ||
201 | goto out_unreg; | ||
202 | |||
203 | return ret; | ||
204 | |||
205 | out_unreg: | ||
206 | xt_unregister_match(AF_INET, &dccp_match); | ||
207 | out_kfree: | ||
208 | kfree(dccp_optbuf); | ||
160 | 209 | ||
161 | return ret; | 210 | return ret; |
162 | } | 211 | } |
163 | 212 | ||
164 | static void __exit fini(void) | 213 | static void __exit fini(void) |
165 | { | 214 | { |
166 | ipt_unregister_match(&dccp_match); | 215 | xt_unregister_match(AF_INET6, &dccp6_match); |
216 | xt_unregister_match(AF_INET, &dccp_match); | ||
167 | kfree(dccp_optbuf); | 217 | kfree(dccp_optbuf); |
168 | } | 218 | } |
169 | 219 | ||
170 | module_init(init); | 220 | module_init(init); |
171 | module_exit(fini); | 221 | module_exit(fini); |
172 | |||
173 | MODULE_LICENSE("GPL"); | ||
174 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | ||
175 | MODULE_DESCRIPTION("Match for DCCP protocol packets"); | ||
176 | |||
diff --git a/net/ipv4/netfilter/ipt_helper.c b/net/netfilter/xt_helper.c index aef649e393af..38b6715e1db4 100644 --- a/net/ipv4/netfilter/ipt_helper.c +++ b/net/netfilter/xt_helper.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <linux/netfilter.h> | 15 | #include <linux/netfilter.h> |
16 | #include <linux/interrupt.h> | ||
17 | #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) | 16 | #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) |
18 | #include <linux/netfilter_ipv4/ip_conntrack.h> | 17 | #include <linux/netfilter_ipv4/ip_conntrack.h> |
19 | #include <linux/netfilter_ipv4/ip_conntrack_core.h> | 18 | #include <linux/netfilter_ipv4/ip_conntrack_core.h> |
@@ -23,12 +22,14 @@ | |||
23 | #include <net/netfilter/nf_conntrack_core.h> | 22 | #include <net/netfilter/nf_conntrack_core.h> |
24 | #include <net/netfilter/nf_conntrack_helper.h> | 23 | #include <net/netfilter/nf_conntrack_helper.h> |
25 | #endif | 24 | #endif |
26 | #include <linux/netfilter_ipv4/ip_tables.h> | 25 | #include <linux/netfilter/x_tables.h> |
27 | #include <linux/netfilter_ipv4/ipt_helper.h> | 26 | #include <linux/netfilter/xt_helper.h> |
28 | 27 | ||
29 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
30 | MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>"); | 29 | MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>"); |
31 | MODULE_DESCRIPTION("iptables helper match module"); | 30 | MODULE_DESCRIPTION("iptables helper match module"); |
31 | MODULE_ALIAS("ipt_helper"); | ||
32 | MODULE_ALIAS("ip6t_helper"); | ||
32 | 33 | ||
33 | #if 0 | 34 | #if 0 |
34 | #define DEBUGP printk | 35 | #define DEBUGP printk |
@@ -43,27 +44,28 @@ match(const struct sk_buff *skb, | |||
43 | const struct net_device *out, | 44 | const struct net_device *out, |
44 | const void *matchinfo, | 45 | const void *matchinfo, |
45 | int offset, | 46 | int offset, |
47 | unsigned int protoff, | ||
46 | int *hotdrop) | 48 | int *hotdrop) |
47 | { | 49 | { |
48 | const struct ipt_helper_info *info = matchinfo; | 50 | const struct xt_helper_info *info = matchinfo; |
49 | struct ip_conntrack *ct; | 51 | struct ip_conntrack *ct; |
50 | enum ip_conntrack_info ctinfo; | 52 | enum ip_conntrack_info ctinfo; |
51 | int ret = info->invert; | 53 | int ret = info->invert; |
52 | 54 | ||
53 | ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); | 55 | ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); |
54 | if (!ct) { | 56 | if (!ct) { |
55 | DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); | 57 | DEBUGP("xt_helper: Eek! invalid conntrack?\n"); |
56 | return ret; | 58 | return ret; |
57 | } | 59 | } |
58 | 60 | ||
59 | if (!ct->master) { | 61 | if (!ct->master) { |
60 | DEBUGP("ipt_helper: conntrack %p has no master\n", ct); | 62 | DEBUGP("xt_helper: conntrack %p has no master\n", ct); |
61 | return ret; | 63 | return ret; |
62 | } | 64 | } |
63 | 65 | ||
64 | read_lock_bh(&ip_conntrack_lock); | 66 | read_lock_bh(&ip_conntrack_lock); |
65 | if (!ct->master->helper) { | 67 | if (!ct->master->helper) { |
66 | DEBUGP("ipt_helper: master ct %p has no helper\n", | 68 | DEBUGP("xt_helper: master ct %p has no helper\n", |
67 | exp->expectant); | 69 | exp->expectant); |
68 | goto out_unlock; | 70 | goto out_unlock; |
69 | } | 71 | } |
@@ -89,27 +91,28 @@ match(const struct sk_buff *skb, | |||
89 | const struct net_device *out, | 91 | const struct net_device *out, |
90 | const void *matchinfo, | 92 | const void *matchinfo, |
91 | int offset, | 93 | int offset, |
94 | unsigned int protoff, | ||
92 | int *hotdrop) | 95 | int *hotdrop) |
93 | { | 96 | { |
94 | const struct ipt_helper_info *info = matchinfo; | 97 | const struct xt_helper_info *info = matchinfo; |
95 | struct nf_conn *ct; | 98 | struct nf_conn *ct; |
96 | enum ip_conntrack_info ctinfo; | 99 | enum ip_conntrack_info ctinfo; |
97 | int ret = info->invert; | 100 | int ret = info->invert; |
98 | 101 | ||
99 | ct = nf_ct_get((struct sk_buff *)skb, &ctinfo); | 102 | ct = nf_ct_get((struct sk_buff *)skb, &ctinfo); |
100 | if (!ct) { | 103 | if (!ct) { |
101 | DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); | 104 | DEBUGP("xt_helper: Eek! invalid conntrack?\n"); |
102 | return ret; | 105 | return ret; |
103 | } | 106 | } |
104 | 107 | ||
105 | if (!ct->master) { | 108 | if (!ct->master) { |
106 | DEBUGP("ipt_helper: conntrack %p has no master\n", ct); | 109 | DEBUGP("xt_helper: conntrack %p has no master\n", ct); |
107 | return ret; | 110 | return ret; |
108 | } | 111 | } |
109 | 112 | ||
110 | read_lock_bh(&nf_conntrack_lock); | 113 | read_lock_bh(&nf_conntrack_lock); |
111 | if (!ct->master->helper) { | 114 | if (!ct->master->helper) { |
112 | DEBUGP("ipt_helper: master ct %p has no helper\n", | 115 | DEBUGP("xt_helper: master ct %p has no helper\n", |
113 | exp->expectant); | 116 | exp->expectant); |
114 | goto out_unlock; | 117 | goto out_unlock; |
115 | } | 118 | } |
@@ -129,23 +132,29 @@ out_unlock: | |||
129 | #endif | 132 | #endif |
130 | 133 | ||
131 | static int check(const char *tablename, | 134 | static int check(const char *tablename, |
132 | const struct ipt_ip *ip, | 135 | const void *inf, |
133 | void *matchinfo, | 136 | void *matchinfo, |
134 | unsigned int matchsize, | 137 | unsigned int matchsize, |
135 | unsigned int hook_mask) | 138 | unsigned int hook_mask) |
136 | { | 139 | { |
137 | struct ipt_helper_info *info = matchinfo; | 140 | struct xt_helper_info *info = matchinfo; |
138 | 141 | ||
139 | info->name[29] = '\0'; | 142 | info->name[29] = '\0'; |
140 | 143 | ||
141 | /* verify size */ | 144 | /* verify size */ |
142 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info))) | 145 | if (matchsize != XT_ALIGN(sizeof(struct xt_helper_info))) |
143 | return 0; | 146 | return 0; |
144 | 147 | ||
145 | return 1; | 148 | return 1; |
146 | } | 149 | } |
147 | 150 | ||
148 | static struct ipt_match helper_match = { | 151 | static struct xt_match helper_match = { |
152 | .name = "helper", | ||
153 | .match = &match, | ||
154 | .checkentry = &check, | ||
155 | .me = THIS_MODULE, | ||
156 | }; | ||
157 | static struct xt_match helper6_match = { | ||
149 | .name = "helper", | 158 | .name = "helper", |
150 | .match = &match, | 159 | .match = &match, |
151 | .checkentry = &check, | 160 | .checkentry = &check, |
@@ -154,13 +163,24 @@ static struct ipt_match helper_match = { | |||
154 | 163 | ||
155 | static int __init init(void) | 164 | static int __init init(void) |
156 | { | 165 | { |
157 | need_ip_conntrack(); | 166 | int ret; |
158 | return ipt_register_match(&helper_match); | 167 | need_conntrack(); |
168 | |||
169 | ret = xt_register_match(AF_INET, &helper_match); | ||
170 | if (ret < 0) | ||
171 | return ret; | ||
172 | |||
173 | ret = xt_register_match(AF_INET6, &helper6_match); | ||
174 | if (ret < 0) | ||
175 | xt_unregister_match(AF_INET, &helper_match); | ||
176 | |||
177 | return ret; | ||
159 | } | 178 | } |
160 | 179 | ||
161 | static void __exit fini(void) | 180 | static void __exit fini(void) |
162 | { | 181 | { |
163 | ipt_unregister_match(&helper_match); | 182 | xt_unregister_match(AF_INET, &helper_match); |
183 | xt_unregister_match(AF_INET6, &helper6_match); | ||
164 | } | 184 | } |
165 | 185 | ||
166 | module_init(init); | 186 | module_init(init); |
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c new file mode 100644 index 000000000000..39c8faea63de --- /dev/null +++ b/net/netfilter/xt_length.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* Kernel module to match packet length. */ | ||
2 | /* (C) 1999-2001 James Morris <jmorros@intercode.com.au> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/skbuff.h> | ||
11 | #include <linux/ipv6.h> | ||
12 | #include <net/ip.h> | ||
13 | |||
14 | #include <linux/netfilter/xt_length.h> | ||
15 | #include <linux/netfilter/x_tables.h> | ||
16 | |||
17 | MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); | ||
18 | MODULE_DESCRIPTION("IP tables packet length matching module"); | ||
19 | MODULE_LICENSE("GPL"); | ||
20 | MODULE_ALIAS("ipt_length"); | ||
21 | MODULE_ALIAS("ip6t_length"); | ||
22 | |||
23 | static int | ||
24 | match(const struct sk_buff *skb, | ||
25 | const struct net_device *in, | ||
26 | const struct net_device *out, | ||
27 | const void *matchinfo, | ||
28 | int offset, | ||
29 | unsigned int protoff, | ||
30 | int *hotdrop) | ||
31 | { | ||
32 | const struct xt_length_info *info = matchinfo; | ||
33 | u_int16_t pktlen = ntohs(skb->nh.iph->tot_len); | ||
34 | |||
35 | return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; | ||
36 | } | ||
37 | |||
38 | static int | ||
39 | match6(const struct sk_buff *skb, | ||
40 | const struct net_device *in, | ||
41 | const struct net_device *out, | ||
42 | const void *matchinfo, | ||
43 | int offset, | ||
44 | unsigned int protoff, | ||
45 | int *hotdrop) | ||
46 | { | ||
47 | const struct xt_length_info *info = matchinfo; | ||
48 | u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr); | ||
49 | |||
50 | return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; | ||
51 | } | ||
52 | |||
53 | static int | ||
54 | checkentry(const char *tablename, | ||
55 | const void *ip, | ||
56 | void *matchinfo, | ||
57 | unsigned int matchsize, | ||
58 | unsigned int hook_mask) | ||
59 | { | ||
60 | if (matchsize != XT_ALIGN(sizeof(struct xt_length_info))) | ||
61 | return 0; | ||
62 | |||
63 | return 1; | ||
64 | } | ||
65 | |||
66 | static struct xt_match length_match = { | ||
67 | .name = "length", | ||
68 | .match = &match, | ||
69 | .checkentry = &checkentry, | ||
70 | .me = THIS_MODULE, | ||
71 | }; | ||
72 | static struct xt_match length6_match = { | ||
73 | .name = "length", | ||
74 | .match = &match6, | ||
75 | .checkentry = &checkentry, | ||
76 | .me = THIS_MODULE, | ||
77 | }; | ||
78 | |||
79 | static int __init init(void) | ||
80 | { | ||
81 | int ret; | ||
82 | ret = xt_register_match(AF_INET, &length_match); | ||
83 | if (ret) | ||
84 | return ret; | ||
85 | ret = xt_register_match(AF_INET6, &length6_match); | ||
86 | if (ret) | ||
87 | xt_unregister_match(AF_INET, &length_match); | ||
88 | |||
89 | return ret; | ||
90 | } | ||
91 | |||
92 | static void __exit fini(void) | ||
93 | { | ||
94 | xt_unregister_match(AF_INET, &length_match); | ||
95 | xt_unregister_match(AF_INET6, &length6_match); | ||
96 | } | ||
97 | |||
98 | module_init(init); | ||
99 | module_exit(fini); | ||
diff --git a/net/ipv4/netfilter/ipt_limit.c b/net/netfilter/xt_limit.c index 0c24dcc703a5..15e40506bc3a 100644 --- a/net/ipv4/netfilter/ipt_limit.c +++ b/net/netfilter/xt_limit.c | |||
@@ -18,12 +18,14 @@ | |||
18 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | 20 | ||
21 | #include <linux/netfilter_ipv4/ip_tables.h> | 21 | #include <linux/netfilter/x_tables.h> |
22 | #include <linux/netfilter_ipv4/ipt_limit.h> | 22 | #include <linux/netfilter/xt_limit.h> |
23 | 23 | ||
24 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
25 | MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>"); | 25 | MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>"); |
26 | MODULE_DESCRIPTION("iptables rate limit match"); | 26 | MODULE_DESCRIPTION("iptables rate limit match"); |
27 | MODULE_ALIAS("ipt_limit"); | ||
28 | MODULE_ALIAS("ip6t_limit"); | ||
27 | 29 | ||
28 | /* The algorithm used is the Simple Token Bucket Filter (TBF) | 30 | /* The algorithm used is the Simple Token Bucket Filter (TBF) |
29 | * see net/sched/sch_tbf.c in the linux source tree | 31 | * see net/sched/sch_tbf.c in the linux source tree |
@@ -68,9 +70,10 @@ ipt_limit_match(const struct sk_buff *skb, | |||
68 | const struct net_device *out, | 70 | const struct net_device *out, |
69 | const void *matchinfo, | 71 | const void *matchinfo, |
70 | int offset, | 72 | int offset, |
73 | unsigned int protoff, | ||
71 | int *hotdrop) | 74 | int *hotdrop) |
72 | { | 75 | { |
73 | struct ipt_rateinfo *r = ((struct ipt_rateinfo *)matchinfo)->master; | 76 | struct xt_rateinfo *r = ((struct xt_rateinfo *)matchinfo)->master; |
74 | unsigned long now = jiffies; | 77 | unsigned long now = jiffies; |
75 | 78 | ||
76 | spin_lock_bh(&limit_lock); | 79 | spin_lock_bh(&limit_lock); |
@@ -96,32 +99,32 @@ user2credits(u_int32_t user) | |||
96 | /* If multiplying would overflow... */ | 99 | /* If multiplying would overflow... */ |
97 | if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) | 100 | if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) |
98 | /* Divide first. */ | 101 | /* Divide first. */ |
99 | return (user / IPT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; | 102 | return (user / XT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; |
100 | 103 | ||
101 | return (user * HZ * CREDITS_PER_JIFFY) / IPT_LIMIT_SCALE; | 104 | return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE; |
102 | } | 105 | } |
103 | 106 | ||
104 | static int | 107 | static int |
105 | ipt_limit_checkentry(const char *tablename, | 108 | ipt_limit_checkentry(const char *tablename, |
106 | const struct ipt_ip *ip, | 109 | const void *inf, |
107 | void *matchinfo, | 110 | void *matchinfo, |
108 | unsigned int matchsize, | 111 | unsigned int matchsize, |
109 | unsigned int hook_mask) | 112 | unsigned int hook_mask) |
110 | { | 113 | { |
111 | struct ipt_rateinfo *r = matchinfo; | 114 | struct xt_rateinfo *r = matchinfo; |
112 | 115 | ||
113 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_rateinfo))) | 116 | if (matchsize != XT_ALIGN(sizeof(struct xt_rateinfo))) |
114 | return 0; | 117 | return 0; |
115 | 118 | ||
116 | /* Check for overflow. */ | 119 | /* Check for overflow. */ |
117 | if (r->burst == 0 | 120 | if (r->burst == 0 |
118 | || user2credits(r->avg * r->burst) < user2credits(r->avg)) { | 121 | || user2credits(r->avg * r->burst) < user2credits(r->avg)) { |
119 | printk("Overflow in ipt_limit, try lower: %u/%u\n", | 122 | printk("Overflow in xt_limit, try lower: %u/%u\n", |
120 | r->avg, r->burst); | 123 | r->avg, r->burst); |
121 | return 0; | 124 | return 0; |
122 | } | 125 | } |
123 | 126 | ||
124 | /* User avg in seconds * IPT_LIMIT_SCALE: convert to jiffies * | 127 | /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * |
125 | 128. */ | 128 | 128. */ |
126 | r->prev = jiffies; | 129 | r->prev = jiffies; |
127 | r->credit = user2credits(r->avg * r->burst); /* Credits full. */ | 130 | r->credit = user2credits(r->avg * r->burst); /* Credits full. */ |
@@ -134,7 +137,13 @@ ipt_limit_checkentry(const char *tablename, | |||
134 | return 1; | 137 | return 1; |
135 | } | 138 | } |
136 | 139 | ||
137 | static struct ipt_match ipt_limit_reg = { | 140 | static struct xt_match ipt_limit_reg = { |
141 | .name = "limit", | ||
142 | .match = ipt_limit_match, | ||
143 | .checkentry = ipt_limit_checkentry, | ||
144 | .me = THIS_MODULE, | ||
145 | }; | ||
146 | static struct xt_match limit6_reg = { | ||
138 | .name = "limit", | 147 | .name = "limit", |
139 | .match = ipt_limit_match, | 148 | .match = ipt_limit_match, |
140 | .checkentry = ipt_limit_checkentry, | 149 | .checkentry = ipt_limit_checkentry, |
@@ -143,14 +152,23 @@ static struct ipt_match ipt_limit_reg = { | |||
143 | 152 | ||
144 | static int __init init(void) | 153 | static int __init init(void) |
145 | { | 154 | { |
146 | if (ipt_register_match(&ipt_limit_reg)) | 155 | int ret; |
147 | return -EINVAL; | 156 | |
148 | return 0; | 157 | ret = xt_register_match(AF_INET, &ipt_limit_reg); |
158 | if (ret) | ||
159 | return ret; | ||
160 | |||
161 | ret = xt_register_match(AF_INET6, &limit6_reg); | ||
162 | if (ret) | ||
163 | xt_unregister_match(AF_INET, &ipt_limit_reg); | ||
164 | |||
165 | return ret; | ||
149 | } | 166 | } |
150 | 167 | ||
151 | static void __exit fini(void) | 168 | static void __exit fini(void) |
152 | { | 169 | { |
153 | ipt_unregister_match(&ipt_limit_reg); | 170 | xt_unregister_match(AF_INET, &ipt_limit_reg); |
171 | xt_unregister_match(AF_INET6, &limit6_reg); | ||
154 | } | 172 | } |
155 | 173 | ||
156 | module_init(init); | 174 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_mac.c b/net/netfilter/xt_mac.c index 1b9bb4559f80..0461dcb5fc7a 100644 --- a/net/ipv4/netfilter/ipt_mac.c +++ b/net/netfilter/xt_mac.c | |||
@@ -13,12 +13,15 @@ | |||
13 | #include <linux/if_ether.h> | 13 | #include <linux/if_ether.h> |
14 | #include <linux/etherdevice.h> | 14 | #include <linux/etherdevice.h> |
15 | 15 | ||
16 | #include <linux/netfilter_ipv4/ipt_mac.h> | 16 | #include <linux/netfilter_ipv4.h> |
17 | #include <linux/netfilter_ipv4/ip_tables.h> | 17 | #include <linux/netfilter/xt_mac.h> |
18 | #include <linux/netfilter/x_tables.h> | ||
18 | 19 | ||
19 | MODULE_LICENSE("GPL"); | 20 | MODULE_LICENSE("GPL"); |
20 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | 21 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); |
21 | MODULE_DESCRIPTION("iptables mac matching module"); | 22 | MODULE_DESCRIPTION("iptables mac matching module"); |
23 | MODULE_ALIAS("ipt_mac"); | ||
24 | MODULE_ALIAS("ip6t_mac"); | ||
22 | 25 | ||
23 | static int | 26 | static int |
24 | match(const struct sk_buff *skb, | 27 | match(const struct sk_buff *skb, |
@@ -26,9 +29,10 @@ match(const struct sk_buff *skb, | |||
26 | const struct net_device *out, | 29 | const struct net_device *out, |
27 | const void *matchinfo, | 30 | const void *matchinfo, |
28 | int offset, | 31 | int offset, |
32 | unsigned int protoff, | ||
29 | int *hotdrop) | 33 | int *hotdrop) |
30 | { | 34 | { |
31 | const struct ipt_mac_info *info = matchinfo; | 35 | const struct xt_mac_info *info = matchinfo; |
32 | 36 | ||
33 | /* Is mac pointer valid? */ | 37 | /* Is mac pointer valid? */ |
34 | return (skb->mac.raw >= skb->head | 38 | return (skb->mac.raw >= skb->head |
@@ -40,7 +44,7 @@ match(const struct sk_buff *skb, | |||
40 | 44 | ||
41 | static int | 45 | static int |
42 | ipt_mac_checkentry(const char *tablename, | 46 | ipt_mac_checkentry(const char *tablename, |
43 | const struct ipt_ip *ip, | 47 | const void *inf, |
44 | void *matchinfo, | 48 | void *matchinfo, |
45 | unsigned int matchsize, | 49 | unsigned int matchsize, |
46 | unsigned int hook_mask) | 50 | unsigned int hook_mask) |
@@ -49,17 +53,23 @@ ipt_mac_checkentry(const char *tablename, | |||
49 | if (hook_mask | 53 | if (hook_mask |
50 | & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | 54 | & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) |
51 | | (1 << NF_IP_FORWARD))) { | 55 | | (1 << NF_IP_FORWARD))) { |
52 | printk("ipt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); | 56 | printk("xt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); |
53 | return 0; | 57 | return 0; |
54 | } | 58 | } |
55 | 59 | ||
56 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_mac_info))) | 60 | if (matchsize != XT_ALIGN(sizeof(struct xt_mac_info))) |
57 | return 0; | 61 | return 0; |
58 | 62 | ||
59 | return 1; | 63 | return 1; |
60 | } | 64 | } |
61 | 65 | ||
62 | static struct ipt_match mac_match = { | 66 | static struct xt_match mac_match = { |
67 | .name = "mac", | ||
68 | .match = &match, | ||
69 | .checkentry = &ipt_mac_checkentry, | ||
70 | .me = THIS_MODULE, | ||
71 | }; | ||
72 | static struct xt_match mac6_match = { | ||
63 | .name = "mac", | 73 | .name = "mac", |
64 | .match = &match, | 74 | .match = &match, |
65 | .checkentry = &ipt_mac_checkentry, | 75 | .checkentry = &ipt_mac_checkentry, |
@@ -68,12 +78,22 @@ static struct ipt_match mac_match = { | |||
68 | 78 | ||
69 | static int __init init(void) | 79 | static int __init init(void) |
70 | { | 80 | { |
71 | return ipt_register_match(&mac_match); | 81 | int ret; |
82 | ret = xt_register_match(AF_INET, &mac_match); | ||
83 | if (ret) | ||
84 | return ret; | ||
85 | |||
86 | ret = xt_register_match(AF_INET6, &mac6_match); | ||
87 | if (ret) | ||
88 | xt_unregister_match(AF_INET, &mac_match); | ||
89 | |||
90 | return ret; | ||
72 | } | 91 | } |
73 | 92 | ||
74 | static void __exit fini(void) | 93 | static void __exit fini(void) |
75 | { | 94 | { |
76 | ipt_unregister_match(&mac_match); | 95 | xt_unregister_match(AF_INET, &mac_match); |
96 | xt_unregister_match(AF_INET6, &mac6_match); | ||
77 | } | 97 | } |
78 | 98 | ||
79 | module_init(init); | 99 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_mark.c b/net/netfilter/xt_mark.c index 00bef6cdd3f8..2a0ac62b72c8 100644 --- a/net/ipv4/netfilter/ipt_mark.c +++ b/net/netfilter/xt_mark.c | |||
@@ -10,12 +10,14 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
12 | 12 | ||
13 | #include <linux/netfilter_ipv4/ipt_mark.h> | 13 | #include <linux/netfilter/xt_mark.h> |
14 | #include <linux/netfilter_ipv4/ip_tables.h> | 14 | #include <linux/netfilter/x_tables.h> |
15 | 15 | ||
16 | MODULE_LICENSE("GPL"); | 16 | MODULE_LICENSE("GPL"); |
17 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | 17 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); |
18 | MODULE_DESCRIPTION("iptables mark matching module"); | 18 | MODULE_DESCRIPTION("iptables mark matching module"); |
19 | MODULE_ALIAS("ipt_mark"); | ||
20 | MODULE_ALIAS("ip6t_mark"); | ||
19 | 21 | ||
20 | static int | 22 | static int |
21 | match(const struct sk_buff *skb, | 23 | match(const struct sk_buff *skb, |
@@ -23,23 +25,24 @@ match(const struct sk_buff *skb, | |||
23 | const struct net_device *out, | 25 | const struct net_device *out, |
24 | const void *matchinfo, | 26 | const void *matchinfo, |
25 | int offset, | 27 | int offset, |
28 | unsigned int protoff, | ||
26 | int *hotdrop) | 29 | int *hotdrop) |
27 | { | 30 | { |
28 | const struct ipt_mark_info *info = matchinfo; | 31 | const struct xt_mark_info *info = matchinfo; |
29 | 32 | ||
30 | return ((skb->nfmark & info->mask) == info->mark) ^ info->invert; | 33 | return ((skb->nfmark & info->mask) == info->mark) ^ info->invert; |
31 | } | 34 | } |
32 | 35 | ||
33 | static int | 36 | static int |
34 | checkentry(const char *tablename, | 37 | checkentry(const char *tablename, |
35 | const struct ipt_ip *ip, | 38 | const void *entry, |
36 | void *matchinfo, | 39 | void *matchinfo, |
37 | unsigned int matchsize, | 40 | unsigned int matchsize, |
38 | unsigned int hook_mask) | 41 | unsigned int hook_mask) |
39 | { | 42 | { |
40 | struct ipt_mark_info *minfo = (struct ipt_mark_info *) matchinfo; | 43 | struct xt_mark_info *minfo = (struct xt_mark_info *) matchinfo; |
41 | 44 | ||
42 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_mark_info))) | 45 | if (matchsize != XT_ALIGN(sizeof(struct xt_mark_info))) |
43 | return 0; | 46 | return 0; |
44 | 47 | ||
45 | if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) { | 48 | if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) { |
@@ -50,7 +53,14 @@ checkentry(const char *tablename, | |||
50 | return 1; | 53 | return 1; |
51 | } | 54 | } |
52 | 55 | ||
53 | static struct ipt_match mark_match = { | 56 | static struct xt_match mark_match = { |
57 | .name = "mark", | ||
58 | .match = &match, | ||
59 | .checkentry = &checkentry, | ||
60 | .me = THIS_MODULE, | ||
61 | }; | ||
62 | |||
63 | static struct xt_match mark6_match = { | ||
54 | .name = "mark", | 64 | .name = "mark", |
55 | .match = &match, | 65 | .match = &match, |
56 | .checkentry = &checkentry, | 66 | .checkentry = &checkentry, |
@@ -59,12 +69,22 @@ static struct ipt_match mark_match = { | |||
59 | 69 | ||
60 | static int __init init(void) | 70 | static int __init init(void) |
61 | { | 71 | { |
62 | return ipt_register_match(&mark_match); | 72 | int ret; |
73 | ret = xt_register_match(AF_INET, &mark_match); | ||
74 | if (ret) | ||
75 | return ret; | ||
76 | |||
77 | ret = xt_register_match(AF_INET6, &mark6_match); | ||
78 | if (ret) | ||
79 | xt_unregister_match(AF_INET, &mark_match); | ||
80 | |||
81 | return ret; | ||
63 | } | 82 | } |
64 | 83 | ||
65 | static void __exit fini(void) | 84 | static void __exit fini(void) |
66 | { | 85 | { |
67 | ipt_unregister_match(&mark_match); | 86 | xt_unregister_match(AF_INET, &mark_match); |
87 | xt_unregister_match(AF_INET6, &mark6_match); | ||
68 | } | 88 | } |
69 | 89 | ||
70 | module_init(init); | 90 | module_init(init); |
diff --git a/net/ipv6/netfilter/ip6t_physdev.c b/net/netfilter/xt_physdev.c index 71515c86ece1..19bb57c14dfe 100644 --- a/net/ipv6/netfilter/ip6t_physdev.c +++ b/net/netfilter/xt_physdev.c | |||
@@ -10,8 +10,8 @@ | |||
10 | 10 | ||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
13 | #include <linux/netfilter_ipv6/ip6t_physdev.h> | 13 | #include <linux/netfilter/xt_physdev.h> |
14 | #include <linux/netfilter_ipv6/ip6_tables.h> | 14 | #include <linux/netfilter/x_tables.h> |
15 | #include <linux/netfilter_bridge.h> | 15 | #include <linux/netfilter_bridge.h> |
16 | #define MATCH 1 | 16 | #define MATCH 1 |
17 | #define NOMATCH 0 | 17 | #define NOMATCH 0 |
@@ -19,6 +19,8 @@ | |||
19 | MODULE_LICENSE("GPL"); | 19 | MODULE_LICENSE("GPL"); |
20 | MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); | 20 | MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); |
21 | MODULE_DESCRIPTION("iptables bridge physical device match module"); | 21 | MODULE_DESCRIPTION("iptables bridge physical device match module"); |
22 | MODULE_ALIAS("ipt_physdev"); | ||
23 | MODULE_ALIAS("ip6t_physdev"); | ||
22 | 24 | ||
23 | static int | 25 | static int |
24 | match(const struct sk_buff *skb, | 26 | match(const struct sk_buff *skb, |
@@ -31,7 +33,7 @@ match(const struct sk_buff *skb, | |||
31 | { | 33 | { |
32 | int i; | 34 | int i; |
33 | static const char nulldevname[IFNAMSIZ]; | 35 | static const char nulldevname[IFNAMSIZ]; |
34 | const struct ip6t_physdev_info *info = matchinfo; | 36 | const struct xt_physdev_info *info = matchinfo; |
35 | unsigned int ret; | 37 | unsigned int ret; |
36 | const char *indev, *outdev; | 38 | const char *indev, *outdev; |
37 | struct nf_bridge_info *nf_bridge; | 39 | struct nf_bridge_info *nf_bridge; |
@@ -41,37 +43,37 @@ match(const struct sk_buff *skb, | |||
41 | * the destination device will be a bridge. */ | 43 | * the destination device will be a bridge. */ |
42 | if (!(nf_bridge = skb->nf_bridge)) { | 44 | if (!(nf_bridge = skb->nf_bridge)) { |
43 | /* Return MATCH if the invert flags of the used options are on */ | 45 | /* Return MATCH if the invert flags of the used options are on */ |
44 | if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) && | 46 | if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && |
45 | !(info->invert & IP6T_PHYSDEV_OP_BRIDGED)) | 47 | !(info->invert & XT_PHYSDEV_OP_BRIDGED)) |
46 | return NOMATCH; | 48 | return NOMATCH; |
47 | if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN) && | 49 | if ((info->bitmask & XT_PHYSDEV_OP_ISIN) && |
48 | !(info->invert & IP6T_PHYSDEV_OP_ISIN)) | 50 | !(info->invert & XT_PHYSDEV_OP_ISIN)) |
49 | return NOMATCH; | 51 | return NOMATCH; |
50 | if ((info->bitmask & IP6T_PHYSDEV_OP_ISOUT) && | 52 | if ((info->bitmask & XT_PHYSDEV_OP_ISOUT) && |
51 | !(info->invert & IP6T_PHYSDEV_OP_ISOUT)) | 53 | !(info->invert & XT_PHYSDEV_OP_ISOUT)) |
52 | return NOMATCH; | 54 | return NOMATCH; |
53 | if ((info->bitmask & IP6T_PHYSDEV_OP_IN) && | 55 | if ((info->bitmask & XT_PHYSDEV_OP_IN) && |
54 | !(info->invert & IP6T_PHYSDEV_OP_IN)) | 56 | !(info->invert & XT_PHYSDEV_OP_IN)) |
55 | return NOMATCH; | 57 | return NOMATCH; |
56 | if ((info->bitmask & IP6T_PHYSDEV_OP_OUT) && | 58 | if ((info->bitmask & XT_PHYSDEV_OP_OUT) && |
57 | !(info->invert & IP6T_PHYSDEV_OP_OUT)) | 59 | !(info->invert & XT_PHYSDEV_OP_OUT)) |
58 | return NOMATCH; | 60 | return NOMATCH; |
59 | return MATCH; | 61 | return MATCH; |
60 | } | 62 | } |
61 | 63 | ||
62 | /* This only makes sense in the FORWARD and POSTROUTING chains */ | 64 | /* This only makes sense in the FORWARD and POSTROUTING chains */ |
63 | if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) && | 65 | if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && |
64 | (!!(nf_bridge->mask & BRNF_BRIDGED) ^ | 66 | (!!(nf_bridge->mask & BRNF_BRIDGED) ^ |
65 | !(info->invert & IP6T_PHYSDEV_OP_BRIDGED))) | 67 | !(info->invert & XT_PHYSDEV_OP_BRIDGED))) |
66 | return NOMATCH; | 68 | return NOMATCH; |
67 | 69 | ||
68 | if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN && | 70 | if ((info->bitmask & XT_PHYSDEV_OP_ISIN && |
69 | (!nf_bridge->physindev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISIN))) || | 71 | (!nf_bridge->physindev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) || |
70 | (info->bitmask & IP6T_PHYSDEV_OP_ISOUT && | 72 | (info->bitmask & XT_PHYSDEV_OP_ISOUT && |
71 | (!nf_bridge->physoutdev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISOUT)))) | 73 | (!nf_bridge->physoutdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT)))) |
72 | return NOMATCH; | 74 | return NOMATCH; |
73 | 75 | ||
74 | if (!(info->bitmask & IP6T_PHYSDEV_OP_IN)) | 76 | if (!(info->bitmask & XT_PHYSDEV_OP_IN)) |
75 | goto match_outdev; | 77 | goto match_outdev; |
76 | indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; | 78 | indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; |
77 | for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { | 79 | for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { |
@@ -80,11 +82,11 @@ match(const struct sk_buff *skb, | |||
80 | & ((const unsigned int *)info->in_mask)[i]; | 82 | & ((const unsigned int *)info->in_mask)[i]; |
81 | } | 83 | } |
82 | 84 | ||
83 | if ((ret == 0) ^ !(info->invert & IP6T_PHYSDEV_OP_IN)) | 85 | if ((ret == 0) ^ !(info->invert & XT_PHYSDEV_OP_IN)) |
84 | return NOMATCH; | 86 | return NOMATCH; |
85 | 87 | ||
86 | match_outdev: | 88 | match_outdev: |
87 | if (!(info->bitmask & IP6T_PHYSDEV_OP_OUT)) | 89 | if (!(info->bitmask & XT_PHYSDEV_OP_OUT)) |
88 | return MATCH; | 90 | return MATCH; |
89 | outdev = nf_bridge->physoutdev ? | 91 | outdev = nf_bridge->physoutdev ? |
90 | nf_bridge->physoutdev->name : nulldevname; | 92 | nf_bridge->physoutdev->name : nulldevname; |
@@ -94,27 +96,34 @@ match_outdev: | |||
94 | & ((const unsigned int *)info->out_mask)[i]; | 96 | & ((const unsigned int *)info->out_mask)[i]; |
95 | } | 97 | } |
96 | 98 | ||
97 | return (ret != 0) ^ !(info->invert & IP6T_PHYSDEV_OP_OUT); | 99 | return (ret != 0) ^ !(info->invert & XT_PHYSDEV_OP_OUT); |
98 | } | 100 | } |
99 | 101 | ||
100 | static int | 102 | static int |
101 | checkentry(const char *tablename, | 103 | checkentry(const char *tablename, |
102 | const struct ip6t_ip6 *ip, | 104 | const void *ip, |
103 | void *matchinfo, | 105 | void *matchinfo, |
104 | unsigned int matchsize, | 106 | unsigned int matchsize, |
105 | unsigned int hook_mask) | 107 | unsigned int hook_mask) |
106 | { | 108 | { |
107 | const struct ip6t_physdev_info *info = matchinfo; | 109 | const struct xt_physdev_info *info = matchinfo; |
108 | 110 | ||
109 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_physdev_info))) | 111 | if (matchsize != XT_ALIGN(sizeof(struct xt_physdev_info))) |
110 | return 0; | 112 | return 0; |
111 | if (!(info->bitmask & IP6T_PHYSDEV_OP_MASK) || | 113 | if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || |
112 | info->bitmask & ~IP6T_PHYSDEV_OP_MASK) | 114 | info->bitmask & ~XT_PHYSDEV_OP_MASK) |
113 | return 0; | 115 | return 0; |
114 | return 1; | 116 | return 1; |
115 | } | 117 | } |
116 | 118 | ||
117 | static struct ip6t_match physdev_match = { | 119 | static struct xt_match physdev_match = { |
120 | .name = "physdev", | ||
121 | .match = &match, | ||
122 | .checkentry = &checkentry, | ||
123 | .me = THIS_MODULE, | ||
124 | }; | ||
125 | |||
126 | static struct xt_match physdev6_match = { | ||
118 | .name = "physdev", | 127 | .name = "physdev", |
119 | .match = &match, | 128 | .match = &match, |
120 | .checkentry = &checkentry, | 129 | .checkentry = &checkentry, |
@@ -123,12 +132,23 @@ static struct ip6t_match physdev_match = { | |||
123 | 132 | ||
124 | static int __init init(void) | 133 | static int __init init(void) |
125 | { | 134 | { |
126 | return ip6t_register_match(&physdev_match); | 135 | int ret; |
136 | |||
137 | ret = xt_register_match(AF_INET, &physdev_match); | ||
138 | if (ret < 0) | ||
139 | return ret; | ||
140 | |||
141 | ret = xt_register_match(AF_INET6, &physdev6_match); | ||
142 | if (ret < 0) | ||
143 | xt_unregister_match(AF_INET, &physdev_match); | ||
144 | |||
145 | return ret; | ||
127 | } | 146 | } |
128 | 147 | ||
129 | static void __exit fini(void) | 148 | static void __exit fini(void) |
130 | { | 149 | { |
131 | ip6t_unregister_match(&physdev_match); | 150 | xt_unregister_match(AF_INET, &physdev_match); |
151 | xt_unregister_match(AF_INET6, &physdev6_match); | ||
132 | } | 152 | } |
133 | 153 | ||
134 | module_init(init); | 154 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_pkttype.c b/net/netfilter/xt_pkttype.c index 8ddb1dc5e5ae..ab1b2630f97d 100644 --- a/net/ipv4/netfilter/ipt_pkttype.c +++ b/net/netfilter/xt_pkttype.c | |||
@@ -10,60 +10,72 @@ | |||
10 | #include <linux/if_ether.h> | 10 | #include <linux/if_ether.h> |
11 | #include <linux/if_packet.h> | 11 | #include <linux/if_packet.h> |
12 | 12 | ||
13 | #include <linux/netfilter_ipv4/ipt_pkttype.h> | 13 | #include <linux/netfilter/xt_pkttype.h> |
14 | #include <linux/netfilter_ipv4/ip_tables.h> | 14 | #include <linux/netfilter/x_tables.h> |
15 | 15 | ||
16 | MODULE_LICENSE("GPL"); | 16 | MODULE_LICENSE("GPL"); |
17 | MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>"); | 17 | MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>"); |
18 | MODULE_DESCRIPTION("IP tables match to match on linklayer packet type"); | 18 | MODULE_DESCRIPTION("IP tables match to match on linklayer packet type"); |
19 | MODULE_ALIAS("ipt_pkttype"); | ||
20 | MODULE_ALIAS("ip6t_pkttype"); | ||
19 | 21 | ||
20 | static int match(const struct sk_buff *skb, | 22 | static int match(const struct sk_buff *skb, |
21 | const struct net_device *in, | 23 | const struct net_device *in, |
22 | const struct net_device *out, | 24 | const struct net_device *out, |
23 | const void *matchinfo, | 25 | const void *matchinfo, |
24 | int offset, | 26 | int offset, |
27 | unsigned int protoff, | ||
25 | int *hotdrop) | 28 | int *hotdrop) |
26 | { | 29 | { |
27 | const struct ipt_pkttype_info *info = matchinfo; | 30 | const struct xt_pkttype_info *info = matchinfo; |
28 | 31 | ||
29 | return (skb->pkt_type == info->pkttype) ^ info->invert; | 32 | return (skb->pkt_type == info->pkttype) ^ info->invert; |
30 | } | 33 | } |
31 | 34 | ||
32 | static int checkentry(const char *tablename, | 35 | static int checkentry(const char *tablename, |
33 | const struct ipt_ip *ip, | 36 | const void *ip, |
34 | void *matchinfo, | 37 | void *matchinfo, |
35 | unsigned int matchsize, | 38 | unsigned int matchsize, |
36 | unsigned int hook_mask) | 39 | unsigned int hook_mask) |
37 | { | 40 | { |
38 | /* | 41 | if (matchsize != XT_ALIGN(sizeof(struct xt_pkttype_info))) |
39 | if (hook_mask | ||
40 | & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | ||
41 | | (1 << NF_IP_FORWARD))) { | ||
42 | printk("ipt_pkttype: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); | ||
43 | return 0; | ||
44 | } | ||
45 | */ | ||
46 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_pkttype_info))) | ||
47 | return 0; | 42 | return 0; |
48 | 43 | ||
49 | return 1; | 44 | return 1; |
50 | } | 45 | } |
51 | 46 | ||
52 | static struct ipt_match pkttype_match = { | 47 | static struct xt_match pkttype_match = { |
53 | .name = "pkttype", | 48 | .name = "pkttype", |
54 | .match = &match, | 49 | .match = &match, |
55 | .checkentry = &checkentry, | 50 | .checkentry = &checkentry, |
56 | .me = THIS_MODULE, | 51 | .me = THIS_MODULE, |
57 | }; | 52 | }; |
53 | static struct xt_match pkttype6_match = { | ||
54 | .name = "pkttype", | ||
55 | .match = &match, | ||
56 | .checkentry = &checkentry, | ||
57 | .me = THIS_MODULE, | ||
58 | }; | ||
59 | |||
58 | 60 | ||
59 | static int __init init(void) | 61 | static int __init init(void) |
60 | { | 62 | { |
61 | return ipt_register_match(&pkttype_match); | 63 | int ret; |
64 | ret = xt_register_match(AF_INET, &pkttype_match); | ||
65 | if (ret) | ||
66 | return ret; | ||
67 | |||
68 | ret = xt_register_match(AF_INET6, &pkttype6_match); | ||
69 | if (ret) | ||
70 | xt_unregister_match(AF_INET, &pkttype_match); | ||
71 | |||
72 | return ret; | ||
62 | } | 73 | } |
63 | 74 | ||
64 | static void __exit fini(void) | 75 | static void __exit fini(void) |
65 | { | 76 | { |
66 | ipt_unregister_match(&pkttype_match); | 77 | xt_unregister_match(AF_INET, &pkttype_match); |
78 | xt_unregister_match(AF_INET6, &pkttype6_match); | ||
67 | } | 79 | } |
68 | 80 | ||
69 | module_init(init); | 81 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_realm.c b/net/netfilter/xt_realm.c index 54a6897ebaa6..2b7e1781d34d 100644 --- a/net/ipv4/netfilter/ipt_realm.c +++ b/net/netfilter/xt_realm.c | |||
@@ -14,12 +14,14 @@ | |||
14 | #include <linux/netdevice.h> | 14 | #include <linux/netdevice.h> |
15 | #include <net/route.h> | 15 | #include <net/route.h> |
16 | 16 | ||
17 | #include <linux/netfilter_ipv4/ipt_realm.h> | 17 | #include <linux/netfilter_ipv4.h> |
18 | #include <linux/netfilter_ipv4/ip_tables.h> | 18 | #include <linux/netfilter/xt_realm.h> |
19 | #include <linux/netfilter/x_tables.h> | ||
19 | 20 | ||
20 | MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>"); | 21 | MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>"); |
21 | MODULE_LICENSE("GPL"); | 22 | MODULE_LICENSE("GPL"); |
22 | MODULE_DESCRIPTION("iptables realm match"); | 23 | MODULE_DESCRIPTION("X_tables realm match"); |
24 | MODULE_ALIAS("ipt_realm"); | ||
23 | 25 | ||
24 | static int | 26 | static int |
25 | match(const struct sk_buff *skb, | 27 | match(const struct sk_buff *skb, |
@@ -27,16 +29,17 @@ match(const struct sk_buff *skb, | |||
27 | const struct net_device *out, | 29 | const struct net_device *out, |
28 | const void *matchinfo, | 30 | const void *matchinfo, |
29 | int offset, | 31 | int offset, |
32 | unsigned int protoff, | ||
30 | int *hotdrop) | 33 | int *hotdrop) |
31 | { | 34 | { |
32 | const struct ipt_realm_info *info = matchinfo; | 35 | const struct xt_realm_info *info = matchinfo; |
33 | struct dst_entry *dst = skb->dst; | 36 | struct dst_entry *dst = skb->dst; |
34 | 37 | ||
35 | return (info->id == (dst->tclassid & info->mask)) ^ info->invert; | 38 | return (info->id == (dst->tclassid & info->mask)) ^ info->invert; |
36 | } | 39 | } |
37 | 40 | ||
38 | static int check(const char *tablename, | 41 | static int check(const char *tablename, |
39 | const struct ipt_ip *ip, | 42 | const void *ip, |
40 | void *matchinfo, | 43 | void *matchinfo, |
41 | unsigned int matchsize, | 44 | unsigned int matchsize, |
42 | unsigned int hook_mask) | 45 | unsigned int hook_mask) |
@@ -44,18 +47,18 @@ static int check(const char *tablename, | |||
44 | if (hook_mask | 47 | if (hook_mask |
45 | & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) | | 48 | & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) | |
46 | (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) { | 49 | (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) { |
47 | printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, " | 50 | printk("xt_realm: only valid for POST_ROUTING, LOCAL_OUT, " |
48 | "LOCAL_IN or FORWARD.\n"); | 51 | "LOCAL_IN or FORWARD.\n"); |
49 | return 0; | 52 | return 0; |
50 | } | 53 | } |
51 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info))) { | 54 | if (matchsize != XT_ALIGN(sizeof(struct xt_realm_info))) { |
52 | printk("ipt_realm: invalid matchsize.\n"); | 55 | printk("xt_realm: invalid matchsize.\n"); |
53 | return 0; | 56 | return 0; |
54 | } | 57 | } |
55 | return 1; | 58 | return 1; |
56 | } | 59 | } |
57 | 60 | ||
58 | static struct ipt_match realm_match = { | 61 | static struct xt_match realm_match = { |
59 | .name = "realm", | 62 | .name = "realm", |
60 | .match = match, | 63 | .match = match, |
61 | .checkentry = check, | 64 | .checkentry = check, |
@@ -64,12 +67,12 @@ static struct ipt_match realm_match = { | |||
64 | 67 | ||
65 | static int __init init(void) | 68 | static int __init init(void) |
66 | { | 69 | { |
67 | return ipt_register_match(&realm_match); | 70 | return xt_register_match(AF_INET, &realm_match); |
68 | } | 71 | } |
69 | 72 | ||
70 | static void __exit fini(void) | 73 | static void __exit fini(void) |
71 | { | 74 | { |
72 | ipt_unregister_match(&realm_match); | 75 | xt_unregister_match(AF_INET, &realm_match); |
73 | } | 76 | } |
74 | 77 | ||
75 | module_init(init); | 78 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_sctp.c b/net/netfilter/xt_sctp.c index fe2b327bcaa4..10fbfc5ba758 100644 --- a/net/ipv4/netfilter/ipt_sctp.c +++ b/net/netfilter/xt_sctp.c | |||
@@ -1,10 +1,18 @@ | |||
1 | #include <linux/module.h> | 1 | #include <linux/module.h> |
2 | #include <linux/skbuff.h> | 2 | #include <linux/skbuff.h> |
3 | #include <net/ip.h> | 3 | #include <net/ip.h> |
4 | #include <net/ipv6.h> | ||
4 | #include <linux/sctp.h> | 5 | #include <linux/sctp.h> |
5 | 6 | ||
7 | #include <linux/netfilter/x_tables.h> | ||
8 | #include <linux/netfilter/xt_sctp.h> | ||
6 | #include <linux/netfilter_ipv4/ip_tables.h> | 9 | #include <linux/netfilter_ipv4/ip_tables.h> |
7 | #include <linux/netfilter_ipv4/ipt_sctp.h> | 10 | #include <linux/netfilter_ipv6/ip6_tables.h> |
11 | |||
12 | MODULE_LICENSE("GPL"); | ||
13 | MODULE_AUTHOR("Kiran Kumar Immidi"); | ||
14 | MODULE_DESCRIPTION("Match for SCTP protocol packets"); | ||
15 | MODULE_ALIAS("ipt_sctp"); | ||
8 | 16 | ||
9 | #ifdef DEBUG_SCTP | 17 | #ifdef DEBUG_SCTP |
10 | #define duprintf(format, args...) printk(format , ## args) | 18 | #define duprintf(format, args...) printk(format , ## args) |
@@ -16,7 +24,7 @@ | |||
16 | || (!!((invflag) & (option)) ^ (cond))) | 24 | || (!!((invflag) & (option)) ^ (cond))) |
17 | 25 | ||
18 | static int | 26 | static int |
19 | match_flags(const struct ipt_sctp_flag_info *flag_info, | 27 | match_flags(const struct xt_sctp_flag_info *flag_info, |
20 | const int flag_count, | 28 | const int flag_count, |
21 | u_int8_t chunktype, | 29 | u_int8_t chunktype, |
22 | u_int8_t chunkflags) | 30 | u_int8_t chunkflags) |
@@ -32,15 +40,15 @@ match_flags(const struct ipt_sctp_flag_info *flag_info, | |||
32 | return 1; | 40 | return 1; |
33 | } | 41 | } |
34 | 42 | ||
35 | static int | 43 | static inline int |
36 | match_packet(const struct sk_buff *skb, | 44 | match_packet(const struct sk_buff *skb, |
45 | unsigned int offset, | ||
37 | const u_int32_t *chunkmap, | 46 | const u_int32_t *chunkmap, |
38 | int chunk_match_type, | 47 | int chunk_match_type, |
39 | const struct ipt_sctp_flag_info *flag_info, | 48 | const struct xt_sctp_flag_info *flag_info, |
40 | const int flag_count, | 49 | const int flag_count, |
41 | int *hotdrop) | 50 | int *hotdrop) |
42 | { | 51 | { |
43 | int offset; | ||
44 | u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)]; | 52 | u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)]; |
45 | sctp_chunkhdr_t _sch, *sch; | 53 | sctp_chunkhdr_t _sch, *sch; |
46 | 54 | ||
@@ -52,7 +60,6 @@ match_packet(const struct sk_buff *skb, | |||
52 | SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap); | 60 | SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap); |
53 | } | 61 | } |
54 | 62 | ||
55 | offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t); | ||
56 | do { | 63 | do { |
57 | sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); | 64 | sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); |
58 | if (sch == NULL) { | 65 | if (sch == NULL) { |
@@ -118,19 +125,20 @@ match(const struct sk_buff *skb, | |||
118 | const struct net_device *out, | 125 | const struct net_device *out, |
119 | const void *matchinfo, | 126 | const void *matchinfo, |
120 | int offset, | 127 | int offset, |
128 | unsigned int protoff, | ||
121 | int *hotdrop) | 129 | int *hotdrop) |
122 | { | 130 | { |
123 | const struct ipt_sctp_info *info; | 131 | const struct xt_sctp_info *info; |
124 | sctp_sctphdr_t _sh, *sh; | 132 | sctp_sctphdr_t _sh, *sh; |
125 | 133 | ||
126 | info = (const struct ipt_sctp_info *)matchinfo; | 134 | info = (const struct xt_sctp_info *)matchinfo; |
127 | 135 | ||
128 | if (offset) { | 136 | if (offset) { |
129 | duprintf("Dropping non-first fragment.. FIXME\n"); | 137 | duprintf("Dropping non-first fragment.. FIXME\n"); |
130 | return 0; | 138 | return 0; |
131 | } | 139 | } |
132 | 140 | ||
133 | sh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_sh), &_sh); | 141 | sh = skb_header_pointer(skb, protoff, sizeof(_sh), &_sh); |
134 | if (sh == NULL) { | 142 | if (sh == NULL) { |
135 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); | 143 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); |
136 | *hotdrop = 1; | 144 | *hotdrop = 1; |
@@ -140,64 +148,103 @@ match(const struct sk_buff *skb, | |||
140 | 148 | ||
141 | return SCCHECK(((ntohs(sh->source) >= info->spts[0]) | 149 | return SCCHECK(((ntohs(sh->source) >= info->spts[0]) |
142 | && (ntohs(sh->source) <= info->spts[1])), | 150 | && (ntohs(sh->source) <= info->spts[1])), |
143 | IPT_SCTP_SRC_PORTS, info->flags, info->invflags) | 151 | XT_SCTP_SRC_PORTS, info->flags, info->invflags) |
144 | && SCCHECK(((ntohs(sh->dest) >= info->dpts[0]) | 152 | && SCCHECK(((ntohs(sh->dest) >= info->dpts[0]) |
145 | && (ntohs(sh->dest) <= info->dpts[1])), | 153 | && (ntohs(sh->dest) <= info->dpts[1])), |
146 | IPT_SCTP_DEST_PORTS, info->flags, info->invflags) | 154 | XT_SCTP_DEST_PORTS, info->flags, info->invflags) |
147 | && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type, | 155 | && SCCHECK(match_packet(skb, protoff, |
156 | info->chunkmap, info->chunk_match_type, | ||
148 | info->flag_info, info->flag_count, | 157 | info->flag_info, info->flag_count, |
149 | hotdrop), | 158 | hotdrop), |
150 | IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags); | 159 | XT_SCTP_CHUNK_TYPES, info->flags, info->invflags); |
151 | } | 160 | } |
152 | 161 | ||
153 | static int | 162 | static int |
154 | checkentry(const char *tablename, | 163 | checkentry(const char *tablename, |
155 | const struct ipt_ip *ip, | 164 | const void *inf, |
165 | void *matchinfo, | ||
166 | unsigned int matchsize, | ||
167 | unsigned int hook_mask) | ||
168 | { | ||
169 | const struct xt_sctp_info *info; | ||
170 | const struct ipt_ip *ip = inf; | ||
171 | |||
172 | info = (const struct xt_sctp_info *)matchinfo; | ||
173 | |||
174 | return ip->proto == IPPROTO_SCTP | ||
175 | && !(ip->invflags & XT_INV_PROTO) | ||
176 | && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info)) | ||
177 | && !(info->flags & ~XT_SCTP_VALID_FLAGS) | ||
178 | && !(info->invflags & ~XT_SCTP_VALID_FLAGS) | ||
179 | && !(info->invflags & ~info->flags) | ||
180 | && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) || | ||
181 | (info->chunk_match_type & | ||
182 | (SCTP_CHUNK_MATCH_ALL | ||
183 | | SCTP_CHUNK_MATCH_ANY | ||
184 | | SCTP_CHUNK_MATCH_ONLY))); | ||
185 | } | ||
186 | |||
187 | static int | ||
188 | checkentry6(const char *tablename, | ||
189 | const void *inf, | ||
156 | void *matchinfo, | 190 | void *matchinfo, |
157 | unsigned int matchsize, | 191 | unsigned int matchsize, |
158 | unsigned int hook_mask) | 192 | unsigned int hook_mask) |
159 | { | 193 | { |
160 | const struct ipt_sctp_info *info; | 194 | const struct xt_sctp_info *info; |
195 | const struct ip6t_ip6 *ip = inf; | ||
161 | 196 | ||
162 | info = (const struct ipt_sctp_info *)matchinfo; | 197 | info = (const struct xt_sctp_info *)matchinfo; |
163 | 198 | ||
164 | return ip->proto == IPPROTO_SCTP | 199 | return ip->proto == IPPROTO_SCTP |
165 | && !(ip->invflags & IPT_INV_PROTO) | 200 | && !(ip->invflags & XT_INV_PROTO) |
166 | && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info)) | 201 | && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info)) |
167 | && !(info->flags & ~IPT_SCTP_VALID_FLAGS) | 202 | && !(info->flags & ~XT_SCTP_VALID_FLAGS) |
168 | && !(info->invflags & ~IPT_SCTP_VALID_FLAGS) | 203 | && !(info->invflags & ~XT_SCTP_VALID_FLAGS) |
169 | && !(info->invflags & ~info->flags) | 204 | && !(info->invflags & ~info->flags) |
170 | && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) || | 205 | && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) || |
171 | (info->chunk_match_type & | 206 | (info->chunk_match_type & |
172 | (SCTP_CHUNK_MATCH_ALL | 207 | (SCTP_CHUNK_MATCH_ALL |
173 | | SCTP_CHUNK_MATCH_ANY | 208 | | SCTP_CHUNK_MATCH_ANY |
174 | | SCTP_CHUNK_MATCH_ONLY))); | 209 | | SCTP_CHUNK_MATCH_ONLY))); |
175 | } | 210 | } |
176 | 211 | ||
177 | static struct ipt_match sctp_match = | 212 | |
213 | static struct xt_match sctp_match = | ||
178 | { | 214 | { |
179 | .list = { NULL, NULL}, | ||
180 | .name = "sctp", | 215 | .name = "sctp", |
181 | .match = &match, | 216 | .match = &match, |
182 | .checkentry = &checkentry, | 217 | .checkentry = &checkentry, |
183 | .destroy = NULL, | 218 | .me = THIS_MODULE |
219 | }; | ||
220 | static struct xt_match sctp6_match = | ||
221 | { | ||
222 | .name = "sctp", | ||
223 | .match = &match, | ||
224 | .checkentry = &checkentry6, | ||
184 | .me = THIS_MODULE | 225 | .me = THIS_MODULE |
185 | }; | 226 | }; |
186 | 227 | ||
228 | |||
187 | static int __init init(void) | 229 | static int __init init(void) |
188 | { | 230 | { |
189 | return ipt_register_match(&sctp_match); | 231 | int ret; |
232 | ret = xt_register_match(AF_INET, &sctp_match); | ||
233 | if (ret) | ||
234 | return ret; | ||
235 | |||
236 | ret = xt_register_match(AF_INET6, &sctp6_match); | ||
237 | if (ret) | ||
238 | xt_unregister_match(AF_INET, &sctp_match); | ||
239 | |||
240 | return ret; | ||
190 | } | 241 | } |
191 | 242 | ||
192 | static void __exit fini(void) | 243 | static void __exit fini(void) |
193 | { | 244 | { |
194 | ipt_unregister_match(&sctp_match); | 245 | xt_unregister_match(AF_INET6, &sctp6_match); |
246 | xt_unregister_match(AF_INET, &sctp_match); | ||
195 | } | 247 | } |
196 | 248 | ||
197 | module_init(init); | 249 | module_init(init); |
198 | module_exit(fini); | 250 | module_exit(fini); |
199 | |||
200 | MODULE_LICENSE("GPL"); | ||
201 | MODULE_AUTHOR("Kiran Kumar Immidi"); | ||
202 | MODULE_DESCRIPTION("Match for SCTP protocol packets"); | ||
203 | |||
diff --git a/net/ipv4/netfilter/ipt_state.c b/net/netfilter/xt_state.c index 4d7f16b70cec..39ce808d40ef 100644 --- a/net/ipv4/netfilter/ipt_state.c +++ b/net/netfilter/xt_state.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* Kernel module to match connection tracking information. */ | 1 | /* Kernel module to match connection tracking information. */ |
2 | 2 | ||
3 | /* (C) 1999-2001 Paul `Rusty' Russell | 3 | /* (C) 1999-2001 Paul `Rusty' Russell |
4 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> | 4 | * (C) 2002-2005 Netfilter Core Team <coreteam@netfilter.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
@@ -11,12 +11,14 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
13 | #include <net/netfilter/nf_conntrack_compat.h> | 13 | #include <net/netfilter/nf_conntrack_compat.h> |
14 | #include <linux/netfilter_ipv4/ip_tables.h> | 14 | #include <linux/netfilter/x_tables.h> |
15 | #include <linux/netfilter_ipv4/ipt_state.h> | 15 | #include <linux/netfilter/xt_state.h> |
16 | 16 | ||
17 | MODULE_LICENSE("GPL"); | 17 | MODULE_LICENSE("GPL"); |
18 | MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>"); | 18 | MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>"); |
19 | MODULE_DESCRIPTION("iptables connection tracking state match module"); | 19 | MODULE_DESCRIPTION("ip[6]_tables connection tracking state match module"); |
20 | MODULE_ALIAS("ipt_state"); | ||
21 | MODULE_ALIAS("ip6t_state"); | ||
20 | 22 | ||
21 | static int | 23 | static int |
22 | match(const struct sk_buff *skb, | 24 | match(const struct sk_buff *skb, |
@@ -24,35 +26,43 @@ match(const struct sk_buff *skb, | |||
24 | const struct net_device *out, | 26 | const struct net_device *out, |
25 | const void *matchinfo, | 27 | const void *matchinfo, |
26 | int offset, | 28 | int offset, |
29 | unsigned int protoff, | ||
27 | int *hotdrop) | 30 | int *hotdrop) |
28 | { | 31 | { |
29 | const struct ipt_state_info *sinfo = matchinfo; | 32 | const struct xt_state_info *sinfo = matchinfo; |
30 | enum ip_conntrack_info ctinfo; | 33 | enum ip_conntrack_info ctinfo; |
31 | unsigned int statebit; | 34 | unsigned int statebit; |
32 | 35 | ||
33 | if (nf_ct_is_untracked(skb)) | 36 | if (nf_ct_is_untracked(skb)) |
34 | statebit = IPT_STATE_UNTRACKED; | 37 | statebit = XT_STATE_UNTRACKED; |
35 | else if (!nf_ct_get_ctinfo(skb, &ctinfo)) | 38 | else if (!nf_ct_get_ctinfo(skb, &ctinfo)) |
36 | statebit = IPT_STATE_INVALID; | 39 | statebit = XT_STATE_INVALID; |
37 | else | 40 | else |
38 | statebit = IPT_STATE_BIT(ctinfo); | 41 | statebit = XT_STATE_BIT(ctinfo); |
39 | 42 | ||
40 | return (sinfo->statemask & statebit); | 43 | return (sinfo->statemask & statebit); |
41 | } | 44 | } |
42 | 45 | ||
43 | static int check(const char *tablename, | 46 | static int check(const char *tablename, |
44 | const struct ipt_ip *ip, | 47 | const void *ip, |
45 | void *matchinfo, | 48 | void *matchinfo, |
46 | unsigned int matchsize, | 49 | unsigned int matchsize, |
47 | unsigned int hook_mask) | 50 | unsigned int hook_mask) |
48 | { | 51 | { |
49 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_state_info))) | 52 | if (matchsize != XT_ALIGN(sizeof(struct xt_state_info))) |
50 | return 0; | 53 | return 0; |
51 | 54 | ||
52 | return 1; | 55 | return 1; |
53 | } | 56 | } |
54 | 57 | ||
55 | static struct ipt_match state_match = { | 58 | static struct xt_match state_match = { |
59 | .name = "state", | ||
60 | .match = &match, | ||
61 | .checkentry = &check, | ||
62 | .me = THIS_MODULE, | ||
63 | }; | ||
64 | |||
65 | static struct xt_match state6_match = { | ||
56 | .name = "state", | 66 | .name = "state", |
57 | .match = &match, | 67 | .match = &match, |
58 | .checkentry = &check, | 68 | .checkentry = &check, |
@@ -61,13 +71,25 @@ static struct ipt_match state_match = { | |||
61 | 71 | ||
62 | static int __init init(void) | 72 | static int __init init(void) |
63 | { | 73 | { |
64 | need_ip_conntrack(); | 74 | int ret; |
65 | return ipt_register_match(&state_match); | 75 | |
76 | need_conntrack(); | ||
77 | |||
78 | ret = xt_register_match(AF_INET, &state_match); | ||
79 | if (ret < 0) | ||
80 | return ret; | ||
81 | |||
82 | ret = xt_register_match(AF_INET6, &state6_match); | ||
83 | if (ret < 0) | ||
84 | xt_unregister_match(AF_INET,&state_match); | ||
85 | |||
86 | return ret; | ||
66 | } | 87 | } |
67 | 88 | ||
68 | static void __exit fini(void) | 89 | static void __exit fini(void) |
69 | { | 90 | { |
70 | ipt_unregister_match(&state_match); | 91 | xt_unregister_match(AF_INET, &state_match); |
92 | xt_unregister_match(AF_INET6, &state6_match); | ||
71 | } | 93 | } |
72 | 94 | ||
73 | module_init(init); | 95 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_string.c b/net/netfilter/xt_string.c index b5def204d798..7c7d5c8807d6 100644 --- a/net/ipv4/netfilter/ipt_string.c +++ b/net/netfilter/xt_string.c | |||
@@ -11,23 +11,26 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/skbuff.h> | 13 | #include <linux/skbuff.h> |
14 | #include <linux/netfilter_ipv4/ip_tables.h> | 14 | #include <linux/netfilter/x_tables.h> |
15 | #include <linux/netfilter_ipv4/ipt_string.h> | 15 | #include <linux/netfilter/xt_string.h> |
16 | #include <linux/textsearch.h> | 16 | #include <linux/textsearch.h> |
17 | 17 | ||
18 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>"); | 18 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>"); |
19 | MODULE_DESCRIPTION("IP tables string match module"); | 19 | MODULE_DESCRIPTION("IP tables string match module"); |
20 | MODULE_LICENSE("GPL"); | 20 | MODULE_LICENSE("GPL"); |
21 | MODULE_ALIAS("ipt_string"); | ||
22 | MODULE_ALIAS("ip6t_string"); | ||
21 | 23 | ||
22 | static int match(const struct sk_buff *skb, | 24 | static int match(const struct sk_buff *skb, |
23 | const struct net_device *in, | 25 | const struct net_device *in, |
24 | const struct net_device *out, | 26 | const struct net_device *out, |
25 | const void *matchinfo, | 27 | const void *matchinfo, |
26 | int offset, | 28 | int offset, |
29 | unsigned int protoff, | ||
27 | int *hotdrop) | 30 | int *hotdrop) |
28 | { | 31 | { |
29 | struct ts_state state; | 32 | struct ts_state state; |
30 | struct ipt_string_info *conf = (struct ipt_string_info *) matchinfo; | 33 | struct xt_string_info *conf = (struct xt_string_info *) matchinfo; |
31 | 34 | ||
32 | memset(&state, 0, sizeof(struct ts_state)); | 35 | memset(&state, 0, sizeof(struct ts_state)); |
33 | 36 | ||
@@ -36,18 +39,18 @@ static int match(const struct sk_buff *skb, | |||
36 | != UINT_MAX) && !conf->invert; | 39 | != UINT_MAX) && !conf->invert; |
37 | } | 40 | } |
38 | 41 | ||
39 | #define STRING_TEXT_PRIV(m) ((struct ipt_string_info *) m) | 42 | #define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m) |
40 | 43 | ||
41 | static int checkentry(const char *tablename, | 44 | static int checkentry(const char *tablename, |
42 | const struct ipt_ip *ip, | 45 | const void *ip, |
43 | void *matchinfo, | 46 | void *matchinfo, |
44 | unsigned int matchsize, | 47 | unsigned int matchsize, |
45 | unsigned int hook_mask) | 48 | unsigned int hook_mask) |
46 | { | 49 | { |
47 | struct ipt_string_info *conf = matchinfo; | 50 | struct xt_string_info *conf = matchinfo; |
48 | struct ts_config *ts_conf; | 51 | struct ts_config *ts_conf; |
49 | 52 | ||
50 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info))) | 53 | if (matchsize != XT_ALIGN(sizeof(struct xt_string_info))) |
51 | return 0; | 54 | return 0; |
52 | 55 | ||
53 | /* Damn, can't handle this case properly with iptables... */ | 56 | /* Damn, can't handle this case properly with iptables... */ |
@@ -69,7 +72,14 @@ static void destroy(void *matchinfo, unsigned int matchsize) | |||
69 | textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config); | 72 | textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config); |
70 | } | 73 | } |
71 | 74 | ||
72 | static struct ipt_match string_match = { | 75 | static struct xt_match string_match = { |
76 | .name = "string", | ||
77 | .match = match, | ||
78 | .checkentry = checkentry, | ||
79 | .destroy = destroy, | ||
80 | .me = THIS_MODULE | ||
81 | }; | ||
82 | static struct xt_match string6_match = { | ||
73 | .name = "string", | 83 | .name = "string", |
74 | .match = match, | 84 | .match = match, |
75 | .checkentry = checkentry, | 85 | .checkentry = checkentry, |
@@ -79,12 +89,22 @@ static struct ipt_match string_match = { | |||
79 | 89 | ||
80 | static int __init init(void) | 90 | static int __init init(void) |
81 | { | 91 | { |
82 | return ipt_register_match(&string_match); | 92 | int ret; |
93 | |||
94 | ret = xt_register_match(AF_INET, &string_match); | ||
95 | if (ret) | ||
96 | return ret; | ||
97 | ret = xt_register_match(AF_INET6, &string6_match); | ||
98 | if (ret) | ||
99 | xt_unregister_match(AF_INET, &string_match); | ||
100 | |||
101 | return ret; | ||
83 | } | 102 | } |
84 | 103 | ||
85 | static void __exit fini(void) | 104 | static void __exit fini(void) |
86 | { | 105 | { |
87 | ipt_unregister_match(&string_match); | 106 | xt_unregister_match(AF_INET, &string_match); |
107 | xt_unregister_match(AF_INET6, &string6_match); | ||
88 | } | 108 | } |
89 | 109 | ||
90 | module_init(init); | 110 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_tcpmss.c b/net/netfilter/xt_tcpmss.c index 4dc9b16ab4a3..acf7f533e9f1 100644 --- a/net/ipv4/netfilter/ipt_tcpmss.c +++ b/net/netfilter/xt_tcpmss.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* Kernel module to match TCP MSS values. */ | 1 | /* Kernel module to match TCP MSS values. */ |
2 | 2 | ||
3 | /* Copyright (C) 2000 Marc Boucher <marc@mbsi.ca> | 3 | /* Copyright (C) 2000 Marc Boucher <marc@mbsi.ca> |
4 | * Portions (C) 2005 by Harald Welte <laforge@netfilter.org> | ||
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
@@ -11,19 +12,24 @@ | |||
11 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
12 | #include <net/tcp.h> | 13 | #include <net/tcp.h> |
13 | 14 | ||
14 | #include <linux/netfilter_ipv4/ipt_tcpmss.h> | 15 | #include <linux/netfilter/xt_tcpmss.h> |
16 | #include <linux/netfilter/x_tables.h> | ||
17 | |||
15 | #include <linux/netfilter_ipv4/ip_tables.h> | 18 | #include <linux/netfilter_ipv4/ip_tables.h> |
19 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
16 | 20 | ||
17 | #define TH_SYN 0x02 | 21 | #define TH_SYN 0x02 |
18 | 22 | ||
19 | MODULE_LICENSE("GPL"); | 23 | MODULE_LICENSE("GPL"); |
20 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | 24 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); |
21 | MODULE_DESCRIPTION("iptables TCP MSS match module"); | 25 | MODULE_DESCRIPTION("iptables TCP MSS match module"); |
26 | MODULE_ALIAS("ipt_tcpmss"); | ||
22 | 27 | ||
23 | /* Returns 1 if the mss option is set and matched by the range, 0 otherwise */ | 28 | /* Returns 1 if the mss option is set and matched by the range, 0 otherwise */ |
24 | static inline int | 29 | static inline int |
25 | mssoption_match(u_int16_t min, u_int16_t max, | 30 | mssoption_match(u_int16_t min, u_int16_t max, |
26 | const struct sk_buff *skb, | 31 | const struct sk_buff *skb, |
32 | unsigned int protoff, | ||
27 | int invert, | 33 | int invert, |
28 | int *hotdrop) | 34 | int *hotdrop) |
29 | { | 35 | { |
@@ -33,8 +39,7 @@ mssoption_match(u_int16_t min, u_int16_t max, | |||
33 | unsigned int i, optlen; | 39 | unsigned int i, optlen; |
34 | 40 | ||
35 | /* If we don't have the whole header, drop packet. */ | 41 | /* If we don't have the whole header, drop packet. */ |
36 | th = skb_header_pointer(skb, skb->nh.iph->ihl * 4, | 42 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); |
37 | sizeof(_tcph), &_tcph); | ||
38 | if (th == NULL) | 43 | if (th == NULL) |
39 | goto dropit; | 44 | goto dropit; |
40 | 45 | ||
@@ -47,8 +52,7 @@ mssoption_match(u_int16_t min, u_int16_t max, | |||
47 | goto out; | 52 | goto out; |
48 | 53 | ||
49 | /* Truncated options. */ | 54 | /* Truncated options. */ |
50 | op = skb_header_pointer(skb, skb->nh.iph->ihl * 4 + sizeof(*th), | 55 | op = skb_header_pointer(skb, protoff + sizeof(*th), optlen, _opt); |
51 | optlen, _opt); | ||
52 | if (op == NULL) | 56 | if (op == NULL) |
53 | goto dropit; | 57 | goto dropit; |
54 | 58 | ||
@@ -79,22 +83,24 @@ match(const struct sk_buff *skb, | |||
79 | const struct net_device *out, | 83 | const struct net_device *out, |
80 | const void *matchinfo, | 84 | const void *matchinfo, |
81 | int offset, | 85 | int offset, |
86 | unsigned int protoff, | ||
82 | int *hotdrop) | 87 | int *hotdrop) |
83 | { | 88 | { |
84 | const struct ipt_tcpmss_match_info *info = matchinfo; | 89 | const struct xt_tcpmss_match_info *info = matchinfo; |
85 | 90 | ||
86 | return mssoption_match(info->mss_min, info->mss_max, skb, | 91 | return mssoption_match(info->mss_min, info->mss_max, skb, protoff, |
87 | info->invert, hotdrop); | 92 | info->invert, hotdrop); |
88 | } | 93 | } |
89 | 94 | ||
90 | static int | 95 | static int |
91 | checkentry(const char *tablename, | 96 | checkentry(const char *tablename, |
92 | const struct ipt_ip *ip, | 97 | const void *ipinfo, |
93 | void *matchinfo, | 98 | void *matchinfo, |
94 | unsigned int matchsize, | 99 | unsigned int matchsize, |
95 | unsigned int hook_mask) | 100 | unsigned int hook_mask) |
96 | { | 101 | { |
97 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_tcpmss_match_info))) | 102 | const struct ipt_ip *ip = ipinfo; |
103 | if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info))) | ||
98 | return 0; | 104 | return 0; |
99 | 105 | ||
100 | /* Must specify -p tcp */ | 106 | /* Must specify -p tcp */ |
@@ -106,21 +112,60 @@ checkentry(const char *tablename, | |||
106 | return 1; | 112 | return 1; |
107 | } | 113 | } |
108 | 114 | ||
109 | static struct ipt_match tcpmss_match = { | 115 | static int |
116 | checkentry6(const char *tablename, | ||
117 | const void *ipinfo, | ||
118 | void *matchinfo, | ||
119 | unsigned int matchsize, | ||
120 | unsigned int hook_mask) | ||
121 | { | ||
122 | const struct ip6t_ip6 *ip = ipinfo; | ||
123 | |||
124 | if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info))) | ||
125 | return 0; | ||
126 | |||
127 | /* Must specify -p tcp */ | ||
128 | if (ip->proto != IPPROTO_TCP || (ip->invflags & XT_INV_PROTO)) { | ||
129 | printk("tcpmss: Only works on TCP packets\n"); | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | return 1; | ||
134 | } | ||
135 | |||
136 | static struct xt_match tcpmss_match = { | ||
110 | .name = "tcpmss", | 137 | .name = "tcpmss", |
111 | .match = &match, | 138 | .match = &match, |
112 | .checkentry = &checkentry, | 139 | .checkentry = &checkentry, |
113 | .me = THIS_MODULE, | 140 | .me = THIS_MODULE, |
114 | }; | 141 | }; |
115 | 142 | ||
143 | static struct xt_match tcpmss6_match = { | ||
144 | .name = "tcpmss", | ||
145 | .match = &match, | ||
146 | .checkentry = &checkentry6, | ||
147 | .me = THIS_MODULE, | ||
148 | }; | ||
149 | |||
150 | |||
116 | static int __init init(void) | 151 | static int __init init(void) |
117 | { | 152 | { |
118 | return ipt_register_match(&tcpmss_match); | 153 | int ret; |
154 | ret = xt_register_match(AF_INET, &tcpmss_match); | ||
155 | if (ret) | ||
156 | return ret; | ||
157 | |||
158 | ret = xt_register_match(AF_INET6, &tcpmss6_match); | ||
159 | if (ret) | ||
160 | xt_unregister_match(AF_INET, &tcpmss_match); | ||
161 | |||
162 | return ret; | ||
119 | } | 163 | } |
120 | 164 | ||
121 | static void __exit fini(void) | 165 | static void __exit fini(void) |
122 | { | 166 | { |
123 | ipt_unregister_match(&tcpmss_match); | 167 | xt_unregister_match(AF_INET6, &tcpmss6_match); |
168 | xt_unregister_match(AF_INET, &tcpmss_match); | ||
124 | } | 169 | } |
125 | 170 | ||
126 | module_init(init); | 171 | module_init(init); |
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c new file mode 100644 index 000000000000..669c8113cc60 --- /dev/null +++ b/net/netfilter/xt_tcpudp.c | |||
@@ -0,0 +1,334 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/module.h> | ||
3 | #include <net/ip.h> | ||
4 | #include <linux/ipv6.h> | ||
5 | #include <net/ipv6.h> | ||
6 | #include <net/tcp.h> | ||
7 | #include <net/udp.h> | ||
8 | #include <linux/netfilter/x_tables.h> | ||
9 | #include <linux/netfilter/xt_tcpudp.h> | ||
10 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
11 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
12 | |||
13 | MODULE_DESCRIPTION("x_tables match for TCP and UDP, supports IPv4 and IPv6"); | ||
14 | MODULE_LICENSE("GPL"); | ||
15 | MODULE_ALIAS("xt_tcp"); | ||
16 | MODULE_ALIAS("xt_udp"); | ||
17 | MODULE_ALIAS("ipt_udp"); | ||
18 | MODULE_ALIAS("ipt_tcp"); | ||
19 | MODULE_ALIAS("ip6t_udp"); | ||
20 | MODULE_ALIAS("ip6t_tcp"); | ||
21 | |||
22 | #ifdef DEBUG_IP_FIREWALL_USER | ||
23 | #define duprintf(format, args...) printk(format , ## args) | ||
24 | #else | ||
25 | #define duprintf(format, args...) | ||
26 | #endif | ||
27 | |||
28 | |||
29 | /* Returns 1 if the port is matched by the range, 0 otherwise */ | ||
30 | static inline int | ||
31 | port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert) | ||
32 | { | ||
33 | int ret; | ||
34 | |||
35 | ret = (port >= min && port <= max) ^ invert; | ||
36 | return ret; | ||
37 | } | ||
38 | |||
39 | static int | ||
40 | tcp_find_option(u_int8_t option, | ||
41 | const struct sk_buff *skb, | ||
42 | unsigned int protoff, | ||
43 | unsigned int optlen, | ||
44 | int invert, | ||
45 | int *hotdrop) | ||
46 | { | ||
47 | /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ | ||
48 | u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; | ||
49 | unsigned int i; | ||
50 | |||
51 | duprintf("tcp_match: finding option\n"); | ||
52 | |||
53 | if (!optlen) | ||
54 | return invert; | ||
55 | |||
56 | /* If we don't have the whole header, drop packet. */ | ||
57 | op = skb_header_pointer(skb, protoff + sizeof(struct tcphdr), | ||
58 | optlen, _opt); | ||
59 | if (op == NULL) { | ||
60 | *hotdrop = 1; | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | for (i = 0; i < optlen; ) { | ||
65 | if (op[i] == option) return !invert; | ||
66 | if (op[i] < 2) i++; | ||
67 | else i += op[i+1]?:1; | ||
68 | } | ||
69 | |||
70 | return invert; | ||
71 | } | ||
72 | |||
73 | static int | ||
74 | tcp_match(const struct sk_buff *skb, | ||
75 | const struct net_device *in, | ||
76 | const struct net_device *out, | ||
77 | const void *matchinfo, | ||
78 | int offset, | ||
79 | unsigned int protoff, | ||
80 | int *hotdrop) | ||
81 | { | ||
82 | struct tcphdr _tcph, *th; | ||
83 | const struct xt_tcp *tcpinfo = matchinfo; | ||
84 | |||
85 | if (offset) { | ||
86 | /* To quote Alan: | ||
87 | |||
88 | Don't allow a fragment of TCP 8 bytes in. Nobody normal | ||
89 | causes this. Its a cracker trying to break in by doing a | ||
90 | flag overwrite to pass the direction checks. | ||
91 | */ | ||
92 | if (offset == 1) { | ||
93 | duprintf("Dropping evil TCP offset=1 frag.\n"); | ||
94 | *hotdrop = 1; | ||
95 | } | ||
96 | /* Must not be a fragment. */ | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) | ||
101 | |||
102 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); | ||
103 | if (th == NULL) { | ||
104 | /* We've been asked to examine this packet, and we | ||
105 | can't. Hence, no choice but to drop. */ | ||
106 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); | ||
107 | *hotdrop = 1; | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], | ||
112 | ntohs(th->source), | ||
113 | !!(tcpinfo->invflags & XT_TCP_INV_SRCPT))) | ||
114 | return 0; | ||
115 | if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], | ||
116 | ntohs(th->dest), | ||
117 | !!(tcpinfo->invflags & XT_TCP_INV_DSTPT))) | ||
118 | return 0; | ||
119 | if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) | ||
120 | == tcpinfo->flg_cmp, | ||
121 | XT_TCP_INV_FLAGS)) | ||
122 | return 0; | ||
123 | if (tcpinfo->option) { | ||
124 | if (th->doff * 4 < sizeof(_tcph)) { | ||
125 | *hotdrop = 1; | ||
126 | return 0; | ||
127 | } | ||
128 | if (!tcp_find_option(tcpinfo->option, skb, protoff, | ||
129 | th->doff*4 - sizeof(_tcph), | ||
130 | tcpinfo->invflags & XT_TCP_INV_OPTION, | ||
131 | hotdrop)) | ||
132 | return 0; | ||
133 | } | ||
134 | return 1; | ||
135 | } | ||
136 | |||
137 | /* Called when user tries to insert an entry of this type. */ | ||
138 | static int | ||
139 | tcp_checkentry(const char *tablename, | ||
140 | const void *info, | ||
141 | void *matchinfo, | ||
142 | unsigned int matchsize, | ||
143 | unsigned int hook_mask) | ||
144 | { | ||
145 | const struct ipt_ip *ip = info; | ||
146 | const struct xt_tcp *tcpinfo = matchinfo; | ||
147 | |||
148 | /* Must specify proto == TCP, and no unknown invflags */ | ||
149 | return ip->proto == IPPROTO_TCP | ||
150 | && !(ip->invflags & XT_INV_PROTO) | ||
151 | && matchsize == XT_ALIGN(sizeof(struct xt_tcp)) | ||
152 | && !(tcpinfo->invflags & ~XT_TCP_INV_MASK); | ||
153 | } | ||
154 | |||
155 | /* Called when user tries to insert an entry of this type. */ | ||
156 | static int | ||
157 | tcp6_checkentry(const char *tablename, | ||
158 | const void *entry, | ||
159 | void *matchinfo, | ||
160 | unsigned int matchsize, | ||
161 | unsigned int hook_mask) | ||
162 | { | ||
163 | const struct ip6t_ip6 *ipv6 = entry; | ||
164 | const struct xt_tcp *tcpinfo = matchinfo; | ||
165 | |||
166 | /* Must specify proto == TCP, and no unknown invflags */ | ||
167 | return ipv6->proto == IPPROTO_TCP | ||
168 | && !(ipv6->invflags & XT_INV_PROTO) | ||
169 | && matchsize == XT_ALIGN(sizeof(struct xt_tcp)) | ||
170 | && !(tcpinfo->invflags & ~XT_TCP_INV_MASK); | ||
171 | } | ||
172 | |||
173 | |||
174 | static int | ||
175 | udp_match(const struct sk_buff *skb, | ||
176 | const struct net_device *in, | ||
177 | const struct net_device *out, | ||
178 | const void *matchinfo, | ||
179 | int offset, | ||
180 | unsigned int protoff, | ||
181 | int *hotdrop) | ||
182 | { | ||
183 | struct udphdr _udph, *uh; | ||
184 | const struct xt_udp *udpinfo = matchinfo; | ||
185 | |||
186 | /* Must not be a fragment. */ | ||
187 | if (offset) | ||
188 | return 0; | ||
189 | |||
190 | uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph); | ||
191 | if (uh == NULL) { | ||
192 | /* We've been asked to examine this packet, and we | ||
193 | can't. Hence, no choice but to drop. */ | ||
194 | duprintf("Dropping evil UDP tinygram.\n"); | ||
195 | *hotdrop = 1; | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | return port_match(udpinfo->spts[0], udpinfo->spts[1], | ||
200 | ntohs(uh->source), | ||
201 | !!(udpinfo->invflags & XT_UDP_INV_SRCPT)) | ||
202 | && port_match(udpinfo->dpts[0], udpinfo->dpts[1], | ||
203 | ntohs(uh->dest), | ||
204 | !!(udpinfo->invflags & XT_UDP_INV_DSTPT)); | ||
205 | } | ||
206 | |||
207 | /* Called when user tries to insert an entry of this type. */ | ||
208 | static int | ||
209 | udp_checkentry(const char *tablename, | ||
210 | const void *info, | ||
211 | void *matchinfo, | ||
212 | unsigned int matchinfosize, | ||
213 | unsigned int hook_mask) | ||
214 | { | ||
215 | const struct ipt_ip *ip = info; | ||
216 | const struct xt_udp *udpinfo = matchinfo; | ||
217 | |||
218 | /* Must specify proto == UDP, and no unknown invflags */ | ||
219 | if (ip->proto != IPPROTO_UDP || (ip->invflags & XT_INV_PROTO)) { | ||
220 | duprintf("ipt_udp: Protocol %u != %u\n", ip->proto, | ||
221 | IPPROTO_UDP); | ||
222 | return 0; | ||
223 | } | ||
224 | if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) { | ||
225 | duprintf("ipt_udp: matchsize %u != %u\n", | ||
226 | matchinfosize, XT_ALIGN(sizeof(struct xt_udp))); | ||
227 | return 0; | ||
228 | } | ||
229 | if (udpinfo->invflags & ~XT_UDP_INV_MASK) { | ||
230 | duprintf("ipt_udp: unknown flags %X\n", | ||
231 | udpinfo->invflags); | ||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | return 1; | ||
236 | } | ||
237 | |||
238 | /* Called when user tries to insert an entry of this type. */ | ||
239 | static int | ||
240 | udp6_checkentry(const char *tablename, | ||
241 | const void *entry, | ||
242 | void *matchinfo, | ||
243 | unsigned int matchinfosize, | ||
244 | unsigned int hook_mask) | ||
245 | { | ||
246 | const struct ip6t_ip6 *ipv6 = entry; | ||
247 | const struct xt_udp *udpinfo = matchinfo; | ||
248 | |||
249 | /* Must specify proto == UDP, and no unknown invflags */ | ||
250 | if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & XT_INV_PROTO)) { | ||
251 | duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto, | ||
252 | IPPROTO_UDP); | ||
253 | return 0; | ||
254 | } | ||
255 | if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) { | ||
256 | duprintf("ip6t_udp: matchsize %u != %u\n", | ||
257 | matchinfosize, XT_ALIGN(sizeof(struct xt_udp))); | ||
258 | return 0; | ||
259 | } | ||
260 | if (udpinfo->invflags & ~XT_UDP_INV_MASK) { | ||
261 | duprintf("ip6t_udp: unknown flags %X\n", | ||
262 | udpinfo->invflags); | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | return 1; | ||
267 | } | ||
268 | |||
269 | static struct xt_match tcp_matchstruct = { | ||
270 | .name = "tcp", | ||
271 | .match = &tcp_match, | ||
272 | .checkentry = &tcp_checkentry, | ||
273 | .me = THIS_MODULE, | ||
274 | }; | ||
275 | static struct xt_match tcp6_matchstruct = { | ||
276 | .name = "tcp", | ||
277 | .match = &tcp_match, | ||
278 | .checkentry = &tcp6_checkentry, | ||
279 | .me = THIS_MODULE, | ||
280 | }; | ||
281 | |||
282 | static struct xt_match udp_matchstruct = { | ||
283 | .name = "udp", | ||
284 | .match = &udp_match, | ||
285 | .checkentry = &udp_checkentry, | ||
286 | .me = THIS_MODULE, | ||
287 | }; | ||
288 | static struct xt_match udp6_matchstruct = { | ||
289 | .name = "udp", | ||
290 | .match = &udp_match, | ||
291 | .checkentry = &udp6_checkentry, | ||
292 | .me = THIS_MODULE, | ||
293 | }; | ||
294 | |||
295 | static int __init init(void) | ||
296 | { | ||
297 | int ret; | ||
298 | ret = xt_register_match(AF_INET, &tcp_matchstruct); | ||
299 | if (ret) | ||
300 | return ret; | ||
301 | |||
302 | ret = xt_register_match(AF_INET6, &tcp6_matchstruct); | ||
303 | if (ret) | ||
304 | goto out_unreg_tcp; | ||
305 | |||
306 | ret = xt_register_match(AF_INET, &udp_matchstruct); | ||
307 | if (ret) | ||
308 | goto out_unreg_tcp6; | ||
309 | |||
310 | ret = xt_register_match(AF_INET6, &udp6_matchstruct); | ||
311 | if (ret) | ||
312 | goto out_unreg_udp; | ||
313 | |||
314 | return ret; | ||
315 | |||
316 | out_unreg_udp: | ||
317 | xt_unregister_match(AF_INET, &tcp_matchstruct); | ||
318 | out_unreg_tcp6: | ||
319 | xt_unregister_match(AF_INET6, &tcp6_matchstruct); | ||
320 | out_unreg_tcp: | ||
321 | xt_unregister_match(AF_INET, &tcp_matchstruct); | ||
322 | return ret; | ||
323 | } | ||
324 | |||
325 | static void __exit fini(void) | ||
326 | { | ||
327 | xt_unregister_match(AF_INET6, &udp6_matchstruct); | ||
328 | xt_unregister_match(AF_INET, &udp_matchstruct); | ||
329 | xt_unregister_match(AF_INET6, &tcp6_matchstruct); | ||
330 | xt_unregister_match(AF_INET, &tcp_matchstruct); | ||
331 | } | ||
332 | |||
333 | module_init(init); | ||
334 | module_exit(fini); | ||
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 3b1378498d50..4ae1538c54a9 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -222,11 +222,6 @@ int genl_register_family(struct genl_family *family) | |||
222 | goto errout_locked; | 222 | goto errout_locked; |
223 | } | 223 | } |
224 | 224 | ||
225 | if (!try_module_get(family->owner)) { | ||
226 | err = -EBUSY; | ||
227 | goto errout_locked; | ||
228 | } | ||
229 | |||
230 | if (family->id == GENL_ID_GENERATE) { | 225 | if (family->id == GENL_ID_GENERATE) { |
231 | u16 newid = genl_generate_id(); | 226 | u16 newid = genl_generate_id(); |
232 | 227 | ||
@@ -283,7 +278,6 @@ int genl_unregister_family(struct genl_family *family) | |||
283 | INIT_LIST_HEAD(&family->ops_list); | 278 | INIT_LIST_HEAD(&family->ops_list); |
284 | genl_unlock(); | 279 | genl_unlock(); |
285 | 280 | ||
286 | module_put(family->owner); | ||
287 | kfree(family->attrbuf); | 281 | kfree(family->attrbuf); |
288 | genl_ctrl_event(CTRL_CMD_DELFAMILY, family); | 282 | genl_ctrl_event(CTRL_CMD_DELFAMILY, family); |
289 | return 0; | 283 | return 0; |
@@ -535,7 +529,6 @@ static struct genl_family genl_ctrl = { | |||
535 | .name = "nlctrl", | 529 | .name = "nlctrl", |
536 | .version = 0x1, | 530 | .version = 0x1, |
537 | .maxattr = CTRL_ATTR_MAX, | 531 | .maxattr = CTRL_ATTR_MAX, |
538 | .owner = THIS_MODULE, | ||
539 | }; | 532 | }; |
540 | 533 | ||
541 | static int __init genl_init(void) | 534 | static int __init genl_init(void) |
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 8a260d43ceef..778b1e5a4b50 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig | |||
@@ -44,7 +44,7 @@ if NET_SCHED | |||
44 | 44 | ||
45 | choice | 45 | choice |
46 | prompt "Packet scheduler clock source" | 46 | prompt "Packet scheduler clock source" |
47 | default NET_SCH_CLK_JIFFIES | 47 | default NET_SCH_CLK_GETTIMEOFDAY |
48 | ---help--- | 48 | ---help--- |
49 | Packet schedulers need a monotonic clock that increments at a static | 49 | Packet schedulers need a monotonic clock that increments at a static |
50 | rate. The kernel provides several suitable interfaces, each with | 50 | rate. The kernel provides several suitable interfaces, each with |
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index b5001939b74b..39a22a3ffe78 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
@@ -62,7 +62,7 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) | |||
62 | struct ipt_target *target; | 62 | struct ipt_target *target; |
63 | int ret = 0; | 63 | int ret = 0; |
64 | 64 | ||
65 | target = ipt_find_target(t->u.user.name, t->u.user.revision); | 65 | target = xt_find_target(AF_INET, t->u.user.name, t->u.user.revision); |
66 | if (!target) | 66 | if (!target) |
67 | return -ENOENT; | 67 | return -ENOENT; |
68 | 68 | ||
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 04c7fab4edc4..2e266129a764 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -180,8 +180,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport, | |||
180 | } | 180 | } |
181 | 181 | ||
182 | SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, " | 182 | SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, " |
183 | "src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " | 183 | "src:" NIP6_FMT " dst:" NIP6_FMT "\n", |
184 | "dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
185 | __FUNCTION__, skb, skb->len, | 184 | __FUNCTION__, skb, skb->len, |
186 | NIP6(fl.fl6_src), NIP6(fl.fl6_dst)); | 185 | NIP6(fl.fl6_src), NIP6(fl.fl6_dst)); |
187 | 186 | ||
@@ -206,13 +205,13 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, | |||
206 | fl.oif = daddr->v6.sin6_scope_id; | 205 | fl.oif = daddr->v6.sin6_scope_id; |
207 | 206 | ||
208 | 207 | ||
209 | SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", | 208 | SCTP_DEBUG_PRINTK("%s: DST=" NIP6_FMT " ", |
210 | __FUNCTION__, NIP6(fl.fl6_dst)); | 209 | __FUNCTION__, NIP6(fl.fl6_dst)); |
211 | 210 | ||
212 | if (saddr) { | 211 | if (saddr) { |
213 | ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr); | 212 | ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr); |
214 | SCTP_DEBUG_PRINTK( | 213 | SCTP_DEBUG_PRINTK( |
215 | "SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x - ", | 214 | "SRC=" NIP6_FMT " - ", |
216 | NIP6(fl.fl6_src)); | 215 | NIP6(fl.fl6_src)); |
217 | } | 216 | } |
218 | 217 | ||
@@ -221,8 +220,7 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, | |||
221 | struct rt6_info *rt; | 220 | struct rt6_info *rt; |
222 | rt = (struct rt6_info *)dst; | 221 | rt = (struct rt6_info *)dst; |
223 | SCTP_DEBUG_PRINTK( | 222 | SCTP_DEBUG_PRINTK( |
224 | "rt6_dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " | 223 | "rt6_dst:" NIP6_FMT " rt6_src:" NIP6_FMT "\n", |
225 | "rt6_src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
226 | NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr)); | 224 | NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr)); |
227 | } else { | 225 | } else { |
228 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); | 226 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); |
@@ -271,13 +269,12 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc, | |||
271 | __u8 bmatchlen; | 269 | __u8 bmatchlen; |
272 | 270 | ||
273 | SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p " | 271 | SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p " |
274 | "daddr:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", | 272 | "daddr:" NIP6_FMT " ", |
275 | __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr)); | 273 | __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr)); |
276 | 274 | ||
277 | if (!asoc) { | 275 | if (!asoc) { |
278 | ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr); | 276 | ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr); |
279 | SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " | 277 | SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " NIP6_FMT "\n", |
280 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
281 | NIP6(saddr->v6.sin6_addr)); | 278 | NIP6(saddr->v6.sin6_addr)); |
282 | return; | 279 | return; |
283 | } | 280 | } |
@@ -305,13 +302,11 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc, | |||
305 | 302 | ||
306 | if (baddr) { | 303 | if (baddr) { |
307 | memcpy(saddr, baddr, sizeof(union sctp_addr)); | 304 | memcpy(saddr, baddr, sizeof(union sctp_addr)); |
308 | SCTP_DEBUG_PRINTK("saddr: " | 305 | SCTP_DEBUG_PRINTK("saddr: " NIP6_FMT "\n", |
309 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
310 | NIP6(saddr->v6.sin6_addr)); | 306 | NIP6(saddr->v6.sin6_addr)); |
311 | } else { | 307 | } else { |
312 | printk(KERN_ERR "%s: asoc:%p Could not find a valid source " | 308 | printk(KERN_ERR "%s: asoc:%p Could not find a valid source " |
313 | "address for the " | 309 | "address for the dest:" NIP6_FMT "\n", |
314 | "dest:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
315 | __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr)); | 310 | __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr)); |
316 | } | 311 | } |
317 | 312 | ||
@@ -675,8 +670,7 @@ static int sctp_v6_is_ce(const struct sk_buff *skb) | |||
675 | /* Dump the v6 addr to the seq file. */ | 670 | /* Dump the v6 addr to the seq file. */ |
676 | static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) | 671 | static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) |
677 | { | 672 | { |
678 | seq_printf(seq, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", | 673 | seq_printf(seq, NIP6_FMT " ", NIP6(addr->v6.sin6_addr)); |
679 | NIP6(addr->v6.sin6_addr)); | ||
680 | } | 674 | } |
681 | 675 | ||
682 | /* Initialize a PF_INET6 socket msg_name. */ | 676 | /* Initialize a PF_INET6 socket msg_name. */ |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 557a7d90b92a..477d7f80dba6 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -1036,14 +1036,14 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, | |||
1036 | if (from_addr.sa.sa_family == AF_INET6) { | 1036 | if (from_addr.sa.sa_family == AF_INET6) { |
1037 | printk(KERN_WARNING | 1037 | printk(KERN_WARNING |
1038 | "%s association %p could not find address " | 1038 | "%s association %p could not find address " |
1039 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | 1039 | NIP6_FMT "\n", |
1040 | __FUNCTION__, | 1040 | __FUNCTION__, |
1041 | asoc, | 1041 | asoc, |
1042 | NIP6(from_addr.v6.sin6_addr)); | 1042 | NIP6(from_addr.v6.sin6_addr)); |
1043 | } else { | 1043 | } else { |
1044 | printk(KERN_WARNING | 1044 | printk(KERN_WARNING |
1045 | "%s association %p could not find address " | 1045 | "%s association %p could not find address " |
1046 | "%u.%u.%u.%u\n", | 1046 | NIPQUAD_FMT "\n", |
1047 | __FUNCTION__, | 1047 | __FUNCTION__, |
1048 | asoc, | 1048 | asoc, |
1049 | NIPQUAD(from_addr.v4.sin_addr.s_addr)); | 1049 | NIPQUAD(from_addr.v4.sin_addr.s_addr)); |
diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig new file mode 100644 index 000000000000..05ab18e62dee --- /dev/null +++ b/net/tipc/Kconfig | |||
@@ -0,0 +1,112 @@ | |||
1 | # | ||
2 | # TIPC configuration | ||
3 | # | ||
4 | |||
5 | menu "TIPC Configuration (EXPERIMENTAL)" | ||
6 | depends on INET && EXPERIMENTAL | ||
7 | |||
8 | config TIPC | ||
9 | tristate "The TIPC Protocol (EXPERIMENTAL)" | ||
10 | ---help--- | ||
11 | TBD. | ||
12 | |||
13 | This protocol support is also available as a module ( = code which | ||
14 | can be inserted in and removed from the running kernel whenever you | ||
15 | want). The module will be called tipc. If you want to compile it | ||
16 | as a module, say M here and read <file:Documentation/modules.txt>. | ||
17 | |||
18 | If in doubt, say N. | ||
19 | |||
20 | config TIPC_ADVANCED | ||
21 | bool "TIPC: Advanced configuration" | ||
22 | depends on TIPC | ||
23 | default n | ||
24 | help | ||
25 | Saying Y here will open some advanced configuration | ||
26 | for TIPC. Most users do not need to bother, so if | ||
27 | unsure, just say N. | ||
28 | |||
29 | config TIPC_ZONES | ||
30 | int "Maximum number of zones in network" | ||
31 | depends on TIPC && TIPC_ADVANCED | ||
32 | default "3" | ||
33 | help | ||
34 | Max number of zones inside TIPC network. Max supported value | ||
35 | is 255 zones, minimum is 1 | ||
36 | |||
37 | Default is 3 zones in a network; setting this to higher | ||
38 | allows more zones but might use more memory. | ||
39 | |||
40 | config TIPC_CLUSTERS | ||
41 | int "Maximum number of clusters in a zone" | ||
42 | depends on TIPC && TIPC_ADVANCED | ||
43 | default "1" | ||
44 | help | ||
45 | ***Only 1 (one cluster in a zone) is supported by current code. | ||
46 | Any value set here will be overridden.*** | ||
47 | |||
48 | (Max number of clusters inside TIPC zone. Max supported | ||
49 | value is 4095 clusters, minimum is 1. | ||
50 | |||
51 | Default is 1; setting this to smaller value might save | ||
52 | some memory, setting it to higher | ||
53 | allows more clusters and might consume more memory.) | ||
54 | |||
55 | config TIPC_NODES | ||
56 | int "Maximum number of nodes in cluster" | ||
57 | depends on TIPC && TIPC_ADVANCED | ||
58 | default "255" | ||
59 | help | ||
60 | Maximum number of nodes inside a TIPC cluster. Maximum | ||
61 | supported value is 2047 nodes, minimum is 8. | ||
62 | |||
63 | Setting this to a smaller value saves some memory, | ||
64 | setting it to higher allows more nodes. | ||
65 | |||
66 | config TIPC_SLAVE_NODES | ||
67 | int "Maximum number of slave nodes in cluster" | ||
68 | depends on TIPC && TIPC_ADVANCED | ||
69 | default "0" | ||
70 | help | ||
71 | ***This capability is not supported by current code.*** | ||
72 | |||
73 | Maximum number of slave nodes inside a TIPC cluster. Maximum | ||
74 | supported value is 2047 nodes, minimum is 0. | ||
75 | |||
76 | Setting this to a smaller value saves some memory, | ||
77 | setting it to higher allows more nodes. | ||
78 | |||
79 | config TIPC_PORTS | ||
80 | int "Maximum number of ports in a node" | ||
81 | depends on TIPC && TIPC_ADVANCED | ||
82 | default "8191" | ||
83 | help | ||
84 | Maximum number of ports within a node. Maximum | ||
85 | supported value is 64535 nodes, minimum is 127. | ||
86 | |||
87 | Setting this to a smaller value saves some memory, | ||
88 | setting it to higher allows more ports. | ||
89 | |||
90 | config TIPC_LOG | ||
91 | int "Size of log buffer" | ||
92 | depends on TIPC && TIPC_ADVANCED | ||
93 | default 0 | ||
94 | help | ||
95 | Size (in bytes) of TIPC's internal log buffer, which records the | ||
96 | occurrence of significant events. Maximum supported value | ||
97 | is 32768 bytes, minimum is 0. | ||
98 | |||
99 | There is no need to enable the log buffer unless the node will be | ||
100 | managed remotely via TIPC. | ||
101 | |||
102 | config TIPC_DEBUG | ||
103 | bool "Enable debugging support" | ||
104 | depends on TIPC | ||
105 | default n | ||
106 | help | ||
107 | This will enable debugging of TIPC. | ||
108 | |||
109 | Only say Y here if you are having trouble with TIPC. It will | ||
110 | enable the display of detailed information about what is going on. | ||
111 | |||
112 | endmenu | ||
diff --git a/net/tipc/Makefile b/net/tipc/Makefile new file mode 100644 index 000000000000..dceb7027946c --- /dev/null +++ b/net/tipc/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | # | ||
2 | # Makefile for the Linux TIPC layer | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_TIPC) := tipc.o | ||
6 | |||
7 | tipc-y += addr.o bcast.o bearer.o config.o cluster.o \ | ||
8 | core.o handler.o link.o discover.o msg.o \ | ||
9 | name_distr.o subscr.o name_table.o net.o \ | ||
10 | netlink.o node.o node_subscr.o port.o ref.o \ | ||
11 | socket.o user_reg.o zone.o dbg.o eth_media.o | ||
12 | |||
13 | # End of file | ||
diff --git a/net/tipc/addr.c b/net/tipc/addr.c new file mode 100644 index 000000000000..eca22260c98c --- /dev/null +++ b/net/tipc/addr.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * net/tipc/addr.c: TIPC address utility routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "dbg.h" | ||
39 | #include "addr.h" | ||
40 | #include "zone.h" | ||
41 | #include "cluster.h" | ||
42 | #include "net.h" | ||
43 | |||
44 | u32 tipc_get_addr(void) | ||
45 | { | ||
46 | return tipc_own_addr; | ||
47 | } | ||
48 | |||
49 | /** | ||
50 | * addr_domain_valid - validates a network domain address | ||
51 | * | ||
52 | * Accepts <Z.C.N>, <Z.C.0>, <Z.0.0>, and <0.0.0>, | ||
53 | * where Z, C, and N are non-zero and do not exceed the configured limits. | ||
54 | * | ||
55 | * Returns 1 if domain address is valid, otherwise 0 | ||
56 | */ | ||
57 | |||
58 | int addr_domain_valid(u32 addr) | ||
59 | { | ||
60 | u32 n = tipc_node(addr); | ||
61 | u32 c = tipc_cluster(addr); | ||
62 | u32 z = tipc_zone(addr); | ||
63 | u32 max_nodes = tipc_max_nodes; | ||
64 | |||
65 | if (is_slave(addr)) | ||
66 | max_nodes = LOWEST_SLAVE + tipc_max_slaves; | ||
67 | if (n > max_nodes) | ||
68 | return 0; | ||
69 | if (c > tipc_max_clusters) | ||
70 | return 0; | ||
71 | if (z > tipc_max_zones) | ||
72 | return 0; | ||
73 | |||
74 | if (n && (!z || !c)) | ||
75 | return 0; | ||
76 | if (c && !z) | ||
77 | return 0; | ||
78 | return 1; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * addr_node_valid - validates a proposed network address for this node | ||
83 | * | ||
84 | * Accepts <Z.C.N>, where Z, C, and N are non-zero and do not exceed | ||
85 | * the configured limits. | ||
86 | * | ||
87 | * Returns 1 if address can be used, otherwise 0 | ||
88 | */ | ||
89 | |||
90 | int addr_node_valid(u32 addr) | ||
91 | { | ||
92 | return (addr_domain_valid(addr) && tipc_node(addr)); | ||
93 | } | ||
94 | |||
diff --git a/net/tipc/addr.h b/net/tipc/addr.h new file mode 100644 index 000000000000..02ca71783e2e --- /dev/null +++ b/net/tipc/addr.h | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * net/tipc/addr.h: Include file for TIPC address utility routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_ADDR_H | ||
38 | #define _TIPC_ADDR_H | ||
39 | |||
40 | static inline u32 own_node(void) | ||
41 | { | ||
42 | return tipc_node(tipc_own_addr); | ||
43 | } | ||
44 | |||
45 | static inline u32 own_cluster(void) | ||
46 | { | ||
47 | return tipc_cluster(tipc_own_addr); | ||
48 | } | ||
49 | |||
50 | static inline u32 own_zone(void) | ||
51 | { | ||
52 | return tipc_zone(tipc_own_addr); | ||
53 | } | ||
54 | |||
55 | static inline int in_own_cluster(u32 addr) | ||
56 | { | ||
57 | return !((addr ^ tipc_own_addr) >> 12); | ||
58 | } | ||
59 | |||
60 | static inline int in_own_zone(u32 addr) | ||
61 | { | ||
62 | return !((addr ^ tipc_own_addr) >> 24); | ||
63 | } | ||
64 | |||
65 | static inline int is_slave(u32 addr) | ||
66 | { | ||
67 | return addr & 0x800; | ||
68 | } | ||
69 | |||
70 | static inline int may_route(u32 addr) | ||
71 | { | ||
72 | return(addr ^ tipc_own_addr) >> 11; | ||
73 | } | ||
74 | |||
75 | static inline int in_scope(u32 domain, u32 addr) | ||
76 | { | ||
77 | if (!domain || (domain == addr)) | ||
78 | return 1; | ||
79 | if (domain == (addr & 0xfffff000u)) /* domain <Z.C.0> */ | ||
80 | return 1; | ||
81 | if (domain == (addr & 0xff000000u)) /* domain <Z.0.0> */ | ||
82 | return 1; | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * addr_scope - convert message lookup domain to equivalent 2-bit scope value | ||
88 | */ | ||
89 | |||
90 | static inline int addr_scope(u32 domain) | ||
91 | { | ||
92 | if (likely(!domain)) | ||
93 | return TIPC_ZONE_SCOPE; | ||
94 | if (tipc_node(domain)) | ||
95 | return TIPC_NODE_SCOPE; | ||
96 | if (tipc_cluster(domain)) | ||
97 | return TIPC_CLUSTER_SCOPE; | ||
98 | return TIPC_ZONE_SCOPE; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * addr_domain - convert 2-bit scope value to equivalent message lookup domain | ||
103 | * | ||
104 | * Needed when address of a named message must be looked up a second time | ||
105 | * after a network hop. | ||
106 | */ | ||
107 | |||
108 | static inline int addr_domain(int sc) | ||
109 | { | ||
110 | if (likely(sc == TIPC_NODE_SCOPE)) | ||
111 | return tipc_own_addr; | ||
112 | if (sc == TIPC_CLUSTER_SCOPE) | ||
113 | return tipc_addr(tipc_zone(tipc_own_addr), | ||
114 | tipc_cluster(tipc_own_addr), 0); | ||
115 | return tipc_addr(tipc_zone(tipc_own_addr), 0, 0); | ||
116 | } | ||
117 | |||
118 | static inline char *addr_string_fill(char *string, u32 addr) | ||
119 | { | ||
120 | snprintf(string, 16, "<%u.%u.%u>", | ||
121 | tipc_zone(addr), tipc_cluster(addr), tipc_node(addr)); | ||
122 | return string; | ||
123 | } | ||
124 | |||
125 | int addr_domain_valid(u32); | ||
126 | int addr_node_valid(u32 addr); | ||
127 | |||
128 | #endif | ||
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c new file mode 100644 index 000000000000..9713d622efb8 --- /dev/null +++ b/net/tipc/bcast.c | |||
@@ -0,0 +1,806 @@ | |||
1 | /* | ||
2 | * net/tipc/bcast.c: TIPC broadcast code | ||
3 | * | ||
4 | * Copyright (c) 2004-2006, Ericsson AB | ||
5 | * Copyright (c) 2004, Intel Corporation. | ||
6 | * Copyright (c) 2005, Wind River Systems | ||
7 | * All rights reserved. | ||
8 | * | ||
9 | * Redistribution and use in source and binary forms, with or without | ||
10 | * modification, are permitted provided that the following conditions are met: | ||
11 | * | ||
12 | * 1. Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * 2. Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in the | ||
16 | * documentation and/or other materials provided with the distribution. | ||
17 | * 3. Neither the names of the copyright holders nor the names of its | ||
18 | * contributors may be used to endorse or promote products derived from | ||
19 | * this software without specific prior written permission. | ||
20 | * | ||
21 | * Alternatively, this software may be distributed under the terms of the | ||
22 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
23 | * Software Foundation. | ||
24 | * | ||
25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
26 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
29 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
35 | * POSSIBILITY OF SUCH DAMAGE. | ||
36 | */ | ||
37 | |||
38 | #include "core.h" | ||
39 | #include "msg.h" | ||
40 | #include "dbg.h" | ||
41 | #include "link.h" | ||
42 | #include "net.h" | ||
43 | #include "node.h" | ||
44 | #include "port.h" | ||
45 | #include "addr.h" | ||
46 | #include "node_subscr.h" | ||
47 | #include "name_distr.h" | ||
48 | #include "bearer.h" | ||
49 | #include "name_table.h" | ||
50 | #include "bcast.h" | ||
51 | |||
52 | |||
53 | #define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */ | ||
54 | |||
55 | #define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */ | ||
56 | |||
57 | #define BCLINK_LOG_BUF_SIZE 0 | ||
58 | |||
59 | /** | ||
60 | * struct bcbearer_pair - a pair of bearers used by broadcast link | ||
61 | * @primary: pointer to primary bearer | ||
62 | * @secondary: pointer to secondary bearer | ||
63 | * | ||
64 | * Bearers must have same priority and same set of reachable destinations | ||
65 | * to be paired. | ||
66 | */ | ||
67 | |||
68 | struct bcbearer_pair { | ||
69 | struct bearer *primary; | ||
70 | struct bearer *secondary; | ||
71 | }; | ||
72 | |||
73 | /** | ||
74 | * struct bcbearer - bearer used by broadcast link | ||
75 | * @bearer: (non-standard) broadcast bearer structure | ||
76 | * @media: (non-standard) broadcast media structure | ||
77 | * @bpairs: array of bearer pairs | ||
78 | * @bpairs_temp: array of bearer pairs used during creation of "bpairs" | ||
79 | */ | ||
80 | |||
81 | struct bcbearer { | ||
82 | struct bearer bearer; | ||
83 | struct media media; | ||
84 | struct bcbearer_pair bpairs[MAX_BEARERS]; | ||
85 | struct bcbearer_pair bpairs_temp[TIPC_NUM_LINK_PRI]; | ||
86 | }; | ||
87 | |||
88 | /** | ||
89 | * struct bclink - link used for broadcast messages | ||
90 | * @link: (non-standard) broadcast link structure | ||
91 | * @node: (non-standard) node structure representing b'cast link's peer node | ||
92 | * | ||
93 | * Handles sequence numbering, fragmentation, bundling, etc. | ||
94 | */ | ||
95 | |||
96 | struct bclink { | ||
97 | struct link link; | ||
98 | struct node node; | ||
99 | }; | ||
100 | |||
101 | |||
102 | static struct bcbearer *bcbearer = NULL; | ||
103 | static struct bclink *bclink = NULL; | ||
104 | static struct link *bcl = NULL; | ||
105 | static spinlock_t bc_lock = SPIN_LOCK_UNLOCKED; | ||
106 | |||
107 | char bc_link_name[] = "multicast-link"; | ||
108 | |||
109 | |||
110 | static inline u32 buf_seqno(struct sk_buff *buf) | ||
111 | { | ||
112 | return msg_seqno(buf_msg(buf)); | ||
113 | } | ||
114 | |||
115 | static inline u32 bcbuf_acks(struct sk_buff *buf) | ||
116 | { | ||
117 | return (u32)(unsigned long)TIPC_SKB_CB(buf)->handle; | ||
118 | } | ||
119 | |||
120 | static inline void bcbuf_set_acks(struct sk_buff *buf, u32 acks) | ||
121 | { | ||
122 | TIPC_SKB_CB(buf)->handle = (void *)(unsigned long)acks; | ||
123 | } | ||
124 | |||
125 | static inline void bcbuf_decr_acks(struct sk_buff *buf) | ||
126 | { | ||
127 | bcbuf_set_acks(buf, bcbuf_acks(buf) - 1); | ||
128 | } | ||
129 | |||
130 | |||
131 | /** | ||
132 | * bclink_set_gap - set gap according to contents of current deferred pkt queue | ||
133 | * | ||
134 | * Called with 'node' locked, bc_lock unlocked | ||
135 | */ | ||
136 | |||
137 | static inline void bclink_set_gap(struct node *n_ptr) | ||
138 | { | ||
139 | struct sk_buff *buf = n_ptr->bclink.deferred_head; | ||
140 | |||
141 | n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = | ||
142 | mod(n_ptr->bclink.last_in); | ||
143 | if (unlikely(buf != NULL)) | ||
144 | n_ptr->bclink.gap_to = mod(buf_seqno(buf) - 1); | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * bclink_ack_allowed - test if ACK or NACK message can be sent at this moment | ||
149 | * | ||
150 | * This mechanism endeavours to prevent all nodes in network from trying | ||
151 | * to ACK or NACK at the same time. | ||
152 | * | ||
153 | * Note: TIPC uses a different trigger to distribute ACKs than it does to | ||
154 | * distribute NACKs, but tries to use the same spacing (divide by 16). | ||
155 | */ | ||
156 | |||
157 | static inline int bclink_ack_allowed(u32 n) | ||
158 | { | ||
159 | return((n % TIPC_MIN_LINK_WIN) == tipc_own_tag); | ||
160 | } | ||
161 | |||
162 | |||
163 | /** | ||
164 | * bclink_retransmit_pkt - retransmit broadcast packets | ||
165 | * @after: sequence number of last packet to *not* retransmit | ||
166 | * @to: sequence number of last packet to retransmit | ||
167 | * | ||
168 | * Called with 'node' locked, bc_lock unlocked | ||
169 | */ | ||
170 | |||
171 | static void bclink_retransmit_pkt(u32 after, u32 to) | ||
172 | { | ||
173 | struct sk_buff *buf; | ||
174 | |||
175 | spin_lock_bh(&bc_lock); | ||
176 | buf = bcl->first_out; | ||
177 | while (buf && less_eq(buf_seqno(buf), after)) { | ||
178 | buf = buf->next; | ||
179 | } | ||
180 | if (buf != NULL) | ||
181 | link_retransmit(bcl, buf, mod(to - after)); | ||
182 | spin_unlock_bh(&bc_lock); | ||
183 | } | ||
184 | |||
185 | /** | ||
186 | * bclink_acknowledge - handle acknowledgement of broadcast packets | ||
187 | * @n_ptr: node that sent acknowledgement info | ||
188 | * @acked: broadcast sequence # that has been acknowledged | ||
189 | * | ||
190 | * Node is locked, bc_lock unlocked. | ||
191 | */ | ||
192 | |||
193 | void bclink_acknowledge(struct node *n_ptr, u32 acked) | ||
194 | { | ||
195 | struct sk_buff *crs; | ||
196 | struct sk_buff *next; | ||
197 | unsigned int released = 0; | ||
198 | |||
199 | if (less_eq(acked, n_ptr->bclink.acked)) | ||
200 | return; | ||
201 | |||
202 | spin_lock_bh(&bc_lock); | ||
203 | |||
204 | /* Skip over packets that node has previously acknowledged */ | ||
205 | |||
206 | crs = bcl->first_out; | ||
207 | while (crs && less_eq(buf_seqno(crs), n_ptr->bclink.acked)) { | ||
208 | crs = crs->next; | ||
209 | } | ||
210 | |||
211 | /* Update packets that node is now acknowledging */ | ||
212 | |||
213 | while (crs && less_eq(buf_seqno(crs), acked)) { | ||
214 | next = crs->next; | ||
215 | bcbuf_decr_acks(crs); | ||
216 | if (bcbuf_acks(crs) == 0) { | ||
217 | bcl->first_out = next; | ||
218 | bcl->out_queue_size--; | ||
219 | buf_discard(crs); | ||
220 | released = 1; | ||
221 | } | ||
222 | crs = next; | ||
223 | } | ||
224 | n_ptr->bclink.acked = acked; | ||
225 | |||
226 | /* Try resolving broadcast link congestion, if necessary */ | ||
227 | |||
228 | if (unlikely(bcl->next_out)) | ||
229 | link_push_queue(bcl); | ||
230 | if (unlikely(released && !list_empty(&bcl->waiting_ports))) | ||
231 | link_wakeup_ports(bcl, 0); | ||
232 | spin_unlock_bh(&bc_lock); | ||
233 | } | ||
234 | |||
235 | /** | ||
236 | * bclink_send_ack - unicast an ACK msg | ||
237 | * | ||
238 | * net_lock and node lock set | ||
239 | */ | ||
240 | |||
241 | static void bclink_send_ack(struct node *n_ptr) | ||
242 | { | ||
243 | struct link *l_ptr = n_ptr->active_links[n_ptr->addr & 1]; | ||
244 | |||
245 | if (l_ptr != NULL) | ||
246 | link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); | ||
247 | } | ||
248 | |||
249 | /** | ||
250 | * bclink_send_nack- broadcast a NACK msg | ||
251 | * | ||
252 | * net_lock and node lock set | ||
253 | */ | ||
254 | |||
255 | static void bclink_send_nack(struct node *n_ptr) | ||
256 | { | ||
257 | struct sk_buff *buf; | ||
258 | struct tipc_msg *msg; | ||
259 | |||
260 | if (!less(n_ptr->bclink.gap_after, n_ptr->bclink.gap_to)) | ||
261 | return; | ||
262 | |||
263 | buf = buf_acquire(INT_H_SIZE); | ||
264 | if (buf) { | ||
265 | msg = buf_msg(buf); | ||
266 | msg_init(msg, BCAST_PROTOCOL, STATE_MSG, | ||
267 | TIPC_OK, INT_H_SIZE, n_ptr->addr); | ||
268 | msg_set_mc_netid(msg, tipc_net_id); | ||
269 | msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in)); | ||
270 | msg_set_bcgap_after(msg, n_ptr->bclink.gap_after); | ||
271 | msg_set_bcgap_to(msg, n_ptr->bclink.gap_to); | ||
272 | msg_set_bcast_tag(msg, tipc_own_tag); | ||
273 | |||
274 | if (bearer_send(&bcbearer->bearer, buf, 0)) { | ||
275 | bcl->stats.sent_nacks++; | ||
276 | buf_discard(buf); | ||
277 | } else { | ||
278 | bearer_schedule(bcl->b_ptr, bcl); | ||
279 | bcl->proto_msg_queue = buf; | ||
280 | bcl->stats.bearer_congs++; | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * Ensure we doesn't send another NACK msg to the node | ||
285 | * until 16 more deferred messages arrive from it | ||
286 | * (i.e. helps prevent all nodes from NACK'ing at same time) | ||
287 | */ | ||
288 | |||
289 | n_ptr->bclink.nack_sync = tipc_own_tag; | ||
290 | } | ||
291 | } | ||
292 | |||
293 | /** | ||
294 | * bclink_check_gap - send a NACK if a sequence gap exists | ||
295 | * | ||
296 | * net_lock and node lock set | ||
297 | */ | ||
298 | |||
299 | void bclink_check_gap(struct node *n_ptr, u32 last_sent) | ||
300 | { | ||
301 | if (!n_ptr->bclink.supported || | ||
302 | less_eq(last_sent, mod(n_ptr->bclink.last_in))) | ||
303 | return; | ||
304 | |||
305 | bclink_set_gap(n_ptr); | ||
306 | if (n_ptr->bclink.gap_after == n_ptr->bclink.gap_to) | ||
307 | n_ptr->bclink.gap_to = last_sent; | ||
308 | bclink_send_nack(n_ptr); | ||
309 | } | ||
310 | |||
311 | /** | ||
312 | * bclink_peek_nack - process a NACK msg meant for another node | ||
313 | * | ||
314 | * Only net_lock set. | ||
315 | */ | ||
316 | |||
317 | void bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 gap_to) | ||
318 | { | ||
319 | struct node *n_ptr = node_find(dest); | ||
320 | u32 my_after, my_to; | ||
321 | |||
322 | if (unlikely(!n_ptr || !node_is_up(n_ptr))) | ||
323 | return; | ||
324 | node_lock(n_ptr); | ||
325 | /* | ||
326 | * Modify gap to suppress unnecessary NACKs from this node | ||
327 | */ | ||
328 | my_after = n_ptr->bclink.gap_after; | ||
329 | my_to = n_ptr->bclink.gap_to; | ||
330 | |||
331 | if (less_eq(gap_after, my_after)) { | ||
332 | if (less(my_after, gap_to) && less(gap_to, my_to)) | ||
333 | n_ptr->bclink.gap_after = gap_to; | ||
334 | else if (less_eq(my_to, gap_to)) | ||
335 | n_ptr->bclink.gap_to = n_ptr->bclink.gap_after; | ||
336 | } else if (less_eq(gap_after, my_to)) { | ||
337 | if (less_eq(my_to, gap_to)) | ||
338 | n_ptr->bclink.gap_to = gap_after; | ||
339 | } else { | ||
340 | /* | ||
341 | * Expand gap if missing bufs not in deferred queue: | ||
342 | */ | ||
343 | struct sk_buff *buf = n_ptr->bclink.deferred_head; | ||
344 | u32 prev = n_ptr->bclink.gap_to; | ||
345 | |||
346 | for (; buf; buf = buf->next) { | ||
347 | u32 seqno = buf_seqno(buf); | ||
348 | |||
349 | if (mod(seqno - prev) != 1) | ||
350 | buf = NULL; | ||
351 | if (seqno == gap_after) | ||
352 | break; | ||
353 | prev = seqno; | ||
354 | } | ||
355 | if (buf == NULL) | ||
356 | n_ptr->bclink.gap_to = gap_after; | ||
357 | } | ||
358 | /* | ||
359 | * Some nodes may send a complementary NACK now: | ||
360 | */ | ||
361 | if (bclink_ack_allowed(sender_tag + 1)) { | ||
362 | if (n_ptr->bclink.gap_to != n_ptr->bclink.gap_after) { | ||
363 | bclink_send_nack(n_ptr); | ||
364 | bclink_set_gap(n_ptr); | ||
365 | } | ||
366 | } | ||
367 | node_unlock(n_ptr); | ||
368 | } | ||
369 | |||
370 | /** | ||
371 | * bclink_send_msg - broadcast a packet to all nodes in cluster | ||
372 | */ | ||
373 | |||
374 | int bclink_send_msg(struct sk_buff *buf) | ||
375 | { | ||
376 | int res; | ||
377 | |||
378 | spin_lock_bh(&bc_lock); | ||
379 | |||
380 | res = link_send_buf(bcl, buf); | ||
381 | if (unlikely(res == -ELINKCONG)) | ||
382 | buf_discard(buf); | ||
383 | else | ||
384 | bcl->stats.sent_info++; | ||
385 | |||
386 | if (bcl->out_queue_size > bcl->stats.max_queue_sz) | ||
387 | bcl->stats.max_queue_sz = bcl->out_queue_size; | ||
388 | bcl->stats.queue_sz_counts++; | ||
389 | bcl->stats.accu_queue_sz += bcl->out_queue_size; | ||
390 | |||
391 | spin_unlock_bh(&bc_lock); | ||
392 | return res; | ||
393 | } | ||
394 | |||
395 | /** | ||
396 | * bclink_recv_pkt - receive a broadcast packet, and deliver upwards | ||
397 | * | ||
398 | * net_lock is read_locked, no other locks set | ||
399 | */ | ||
400 | |||
401 | void bclink_recv_pkt(struct sk_buff *buf) | ||
402 | { | ||
403 | struct tipc_msg *msg = buf_msg(buf); | ||
404 | struct node* node = node_find(msg_prevnode(msg)); | ||
405 | u32 next_in; | ||
406 | u32 seqno; | ||
407 | struct sk_buff *deferred; | ||
408 | |||
409 | msg_dbg(msg, "<BC<<<"); | ||
410 | |||
411 | if (unlikely(!node || !node_is_up(node) || !node->bclink.supported || | ||
412 | (msg_mc_netid(msg) != tipc_net_id))) { | ||
413 | buf_discard(buf); | ||
414 | return; | ||
415 | } | ||
416 | |||
417 | if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) { | ||
418 | msg_dbg(msg, "<BCNACK<<<"); | ||
419 | if (msg_destnode(msg) == tipc_own_addr) { | ||
420 | node_lock(node); | ||
421 | bclink_acknowledge(node, msg_bcast_ack(msg)); | ||
422 | node_unlock(node); | ||
423 | bcl->stats.recv_nacks++; | ||
424 | bclink_retransmit_pkt(msg_bcgap_after(msg), | ||
425 | msg_bcgap_to(msg)); | ||
426 | } else { | ||
427 | bclink_peek_nack(msg_destnode(msg), | ||
428 | msg_bcast_tag(msg), | ||
429 | msg_bcgap_after(msg), | ||
430 | msg_bcgap_to(msg)); | ||
431 | } | ||
432 | buf_discard(buf); | ||
433 | return; | ||
434 | } | ||
435 | |||
436 | node_lock(node); | ||
437 | receive: | ||
438 | deferred = node->bclink.deferred_head; | ||
439 | next_in = mod(node->bclink.last_in + 1); | ||
440 | seqno = msg_seqno(msg); | ||
441 | |||
442 | if (likely(seqno == next_in)) { | ||
443 | bcl->stats.recv_info++; | ||
444 | node->bclink.last_in++; | ||
445 | bclink_set_gap(node); | ||
446 | if (unlikely(bclink_ack_allowed(seqno))) { | ||
447 | bclink_send_ack(node); | ||
448 | bcl->stats.sent_acks++; | ||
449 | } | ||
450 | if (likely(msg_isdata(msg))) { | ||
451 | node_unlock(node); | ||
452 | port_recv_mcast(buf, NULL); | ||
453 | } else if (msg_user(msg) == MSG_BUNDLER) { | ||
454 | bcl->stats.recv_bundles++; | ||
455 | bcl->stats.recv_bundled += msg_msgcnt(msg); | ||
456 | node_unlock(node); | ||
457 | link_recv_bundle(buf); | ||
458 | } else if (msg_user(msg) == MSG_FRAGMENTER) { | ||
459 | bcl->stats.recv_fragments++; | ||
460 | if (link_recv_fragment(&node->bclink.defragm, | ||
461 | &buf, &msg)) | ||
462 | bcl->stats.recv_fragmented++; | ||
463 | node_unlock(node); | ||
464 | net_route_msg(buf); | ||
465 | } else { | ||
466 | node_unlock(node); | ||
467 | net_route_msg(buf); | ||
468 | } | ||
469 | if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) { | ||
470 | node_lock(node); | ||
471 | buf = deferred; | ||
472 | msg = buf_msg(buf); | ||
473 | node->bclink.deferred_head = deferred->next; | ||
474 | goto receive; | ||
475 | } | ||
476 | return; | ||
477 | } else if (less(next_in, seqno)) { | ||
478 | u32 gap_after = node->bclink.gap_after; | ||
479 | u32 gap_to = node->bclink.gap_to; | ||
480 | |||
481 | if (link_defer_pkt(&node->bclink.deferred_head, | ||
482 | &node->bclink.deferred_tail, | ||
483 | buf)) { | ||
484 | node->bclink.nack_sync++; | ||
485 | bcl->stats.deferred_recv++; | ||
486 | if (seqno == mod(gap_after + 1)) | ||
487 | node->bclink.gap_after = seqno; | ||
488 | else if (less(gap_after, seqno) && less(seqno, gap_to)) | ||
489 | node->bclink.gap_to = seqno; | ||
490 | } | ||
491 | if (bclink_ack_allowed(node->bclink.nack_sync)) { | ||
492 | if (gap_to != gap_after) | ||
493 | bclink_send_nack(node); | ||
494 | bclink_set_gap(node); | ||
495 | } | ||
496 | } else { | ||
497 | bcl->stats.duplicates++; | ||
498 | buf_discard(buf); | ||
499 | } | ||
500 | node_unlock(node); | ||
501 | } | ||
502 | |||
503 | u32 bclink_get_last_sent(void) | ||
504 | { | ||
505 | u32 last_sent = mod(bcl->next_out_no - 1); | ||
506 | |||
507 | if (bcl->next_out) | ||
508 | last_sent = mod(buf_seqno(bcl->next_out) - 1); | ||
509 | return last_sent; | ||
510 | } | ||
511 | |||
512 | u32 bclink_acks_missing(struct node *n_ptr) | ||
513 | { | ||
514 | return (n_ptr->bclink.supported && | ||
515 | (bclink_get_last_sent() != n_ptr->bclink.acked)); | ||
516 | } | ||
517 | |||
518 | |||
519 | /** | ||
520 | * bcbearer_send - send a packet through the broadcast pseudo-bearer | ||
521 | * | ||
522 | * Send through as many bearers as necessary to reach all nodes | ||
523 | * that support TIPC multicasting. | ||
524 | * | ||
525 | * Returns 0 if packet sent successfully, non-zero if not | ||
526 | */ | ||
527 | |||
528 | int bcbearer_send(struct sk_buff *buf, | ||
529 | struct tipc_bearer *unused1, | ||
530 | struct tipc_media_addr *unused2) | ||
531 | { | ||
532 | static int send_count = 0; | ||
533 | |||
534 | struct node_map remains; | ||
535 | struct node_map remains_new; | ||
536 | int bp_index; | ||
537 | int swap_time; | ||
538 | |||
539 | /* Prepare buffer for broadcasting (if first time trying to send it) */ | ||
540 | |||
541 | if (likely(!msg_non_seq(buf_msg(buf)))) { | ||
542 | struct tipc_msg *msg; | ||
543 | |||
544 | assert(cluster_bcast_nodes.count != 0); | ||
545 | bcbuf_set_acks(buf, cluster_bcast_nodes.count); | ||
546 | msg = buf_msg(buf); | ||
547 | msg_set_non_seq(msg); | ||
548 | msg_set_mc_netid(msg, tipc_net_id); | ||
549 | } | ||
550 | |||
551 | /* Determine if bearer pairs should be swapped following this attempt */ | ||
552 | |||
553 | if ((swap_time = (++send_count >= 10))) | ||
554 | send_count = 0; | ||
555 | |||
556 | /* Send buffer over bearers until all targets reached */ | ||
557 | |||
558 | remains = cluster_bcast_nodes; | ||
559 | |||
560 | for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) { | ||
561 | struct bearer *p = bcbearer->bpairs[bp_index].primary; | ||
562 | struct bearer *s = bcbearer->bpairs[bp_index].secondary; | ||
563 | |||
564 | if (!p) | ||
565 | break; /* no more bearers to try */ | ||
566 | |||
567 | nmap_diff(&remains, &p->nodes, &remains_new); | ||
568 | if (remains_new.count == remains.count) | ||
569 | continue; /* bearer pair doesn't add anything */ | ||
570 | |||
571 | if (!p->publ.blocked && | ||
572 | !p->media->send_msg(buf, &p->publ, &p->media->bcast_addr)) { | ||
573 | if (swap_time && s && !s->publ.blocked) | ||
574 | goto swap; | ||
575 | else | ||
576 | goto update; | ||
577 | } | ||
578 | |||
579 | if (!s || s->publ.blocked || | ||
580 | s->media->send_msg(buf, &s->publ, &s->media->bcast_addr)) | ||
581 | continue; /* unable to send using bearer pair */ | ||
582 | swap: | ||
583 | bcbearer->bpairs[bp_index].primary = s; | ||
584 | bcbearer->bpairs[bp_index].secondary = p; | ||
585 | update: | ||
586 | if (remains_new.count == 0) | ||
587 | return TIPC_OK; | ||
588 | |||
589 | remains = remains_new; | ||
590 | } | ||
591 | |||
592 | /* Unable to reach all targets */ | ||
593 | |||
594 | bcbearer->bearer.publ.blocked = 1; | ||
595 | bcl->stats.bearer_congs++; | ||
596 | return ~TIPC_OK; | ||
597 | } | ||
598 | |||
599 | /** | ||
600 | * bcbearer_sort - create sets of bearer pairs used by broadcast bearer | ||
601 | */ | ||
602 | |||
603 | void bcbearer_sort(void) | ||
604 | { | ||
605 | struct bcbearer_pair *bp_temp = bcbearer->bpairs_temp; | ||
606 | struct bcbearer_pair *bp_curr; | ||
607 | int b_index; | ||
608 | int pri; | ||
609 | |||
610 | spin_lock_bh(&bc_lock); | ||
611 | |||
612 | /* Group bearers by priority (can assume max of two per priority) */ | ||
613 | |||
614 | memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp)); | ||
615 | |||
616 | for (b_index = 0; b_index < MAX_BEARERS; b_index++) { | ||
617 | struct bearer *b = &bearers[b_index]; | ||
618 | |||
619 | if (!b->active || !b->nodes.count) | ||
620 | continue; | ||
621 | |||
622 | if (!bp_temp[b->priority].primary) | ||
623 | bp_temp[b->priority].primary = b; | ||
624 | else | ||
625 | bp_temp[b->priority].secondary = b; | ||
626 | } | ||
627 | |||
628 | /* Create array of bearer pairs for broadcasting */ | ||
629 | |||
630 | bp_curr = bcbearer->bpairs; | ||
631 | memset(bcbearer->bpairs, 0, sizeof(bcbearer->bpairs)); | ||
632 | |||
633 | for (pri = (TIPC_NUM_LINK_PRI - 1); pri >= 0; pri--) { | ||
634 | |||
635 | if (!bp_temp[pri].primary) | ||
636 | continue; | ||
637 | |||
638 | bp_curr->primary = bp_temp[pri].primary; | ||
639 | |||
640 | if (bp_temp[pri].secondary) { | ||
641 | if (nmap_equal(&bp_temp[pri].primary->nodes, | ||
642 | &bp_temp[pri].secondary->nodes)) { | ||
643 | bp_curr->secondary = bp_temp[pri].secondary; | ||
644 | } else { | ||
645 | bp_curr++; | ||
646 | bp_curr->primary = bp_temp[pri].secondary; | ||
647 | } | ||
648 | } | ||
649 | |||
650 | bp_curr++; | ||
651 | } | ||
652 | |||
653 | spin_unlock_bh(&bc_lock); | ||
654 | } | ||
655 | |||
656 | /** | ||
657 | * bcbearer_push - resolve bearer congestion | ||
658 | * | ||
659 | * Forces bclink to push out any unsent packets, until all packets are gone | ||
660 | * or congestion reoccurs. | ||
661 | * No locks set when function called | ||
662 | */ | ||
663 | |||
664 | void bcbearer_push(void) | ||
665 | { | ||
666 | struct bearer *b_ptr; | ||
667 | |||
668 | spin_lock_bh(&bc_lock); | ||
669 | b_ptr = &bcbearer->bearer; | ||
670 | if (b_ptr->publ.blocked) { | ||
671 | b_ptr->publ.blocked = 0; | ||
672 | bearer_lock_push(b_ptr); | ||
673 | } | ||
674 | spin_unlock_bh(&bc_lock); | ||
675 | } | ||
676 | |||
677 | |||
678 | int bclink_stats(char *buf, const u32 buf_size) | ||
679 | { | ||
680 | struct print_buf pb; | ||
681 | |||
682 | if (!bcl) | ||
683 | return 0; | ||
684 | |||
685 | printbuf_init(&pb, buf, buf_size); | ||
686 | |||
687 | spin_lock_bh(&bc_lock); | ||
688 | |||
689 | tipc_printf(&pb, "Link <%s>\n" | ||
690 | " Window:%u packets\n", | ||
691 | bcl->name, bcl->queue_limit[0]); | ||
692 | tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
693 | bcl->stats.recv_info, | ||
694 | bcl->stats.recv_fragments, | ||
695 | bcl->stats.recv_fragmented, | ||
696 | bcl->stats.recv_bundles, | ||
697 | bcl->stats.recv_bundled); | ||
698 | tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
699 | bcl->stats.sent_info, | ||
700 | bcl->stats.sent_fragments, | ||
701 | bcl->stats.sent_fragmented, | ||
702 | bcl->stats.sent_bundles, | ||
703 | bcl->stats.sent_bundled); | ||
704 | tipc_printf(&pb, " RX naks:%u defs:%u dups:%u\n", | ||
705 | bcl->stats.recv_nacks, | ||
706 | bcl->stats.deferred_recv, | ||
707 | bcl->stats.duplicates); | ||
708 | tipc_printf(&pb, " TX naks:%u acks:%u dups:%u\n", | ||
709 | bcl->stats.sent_nacks, | ||
710 | bcl->stats.sent_acks, | ||
711 | bcl->stats.retransmitted); | ||
712 | tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n", | ||
713 | bcl->stats.bearer_congs, | ||
714 | bcl->stats.link_congs, | ||
715 | bcl->stats.max_queue_sz, | ||
716 | bcl->stats.queue_sz_counts | ||
717 | ? (bcl->stats.accu_queue_sz / bcl->stats.queue_sz_counts) | ||
718 | : 0); | ||
719 | |||
720 | spin_unlock_bh(&bc_lock); | ||
721 | return printbuf_validate(&pb); | ||
722 | } | ||
723 | |||
724 | int bclink_reset_stats(void) | ||
725 | { | ||
726 | if (!bcl) | ||
727 | return -ENOPROTOOPT; | ||
728 | |||
729 | spin_lock_bh(&bc_lock); | ||
730 | memset(&bcl->stats, 0, sizeof(bcl->stats)); | ||
731 | spin_unlock_bh(&bc_lock); | ||
732 | return TIPC_OK; | ||
733 | } | ||
734 | |||
735 | int bclink_set_queue_limits(u32 limit) | ||
736 | { | ||
737 | if (!bcl) | ||
738 | return -ENOPROTOOPT; | ||
739 | if ((limit < TIPC_MIN_LINK_WIN) || (limit > TIPC_MAX_LINK_WIN)) | ||
740 | return -EINVAL; | ||
741 | |||
742 | spin_lock_bh(&bc_lock); | ||
743 | link_set_queue_limits(bcl, limit); | ||
744 | spin_unlock_bh(&bc_lock); | ||
745 | return TIPC_OK; | ||
746 | } | ||
747 | |||
748 | int bclink_init(void) | ||
749 | { | ||
750 | bcbearer = kmalloc(sizeof(*bcbearer), GFP_ATOMIC); | ||
751 | bclink = kmalloc(sizeof(*bclink), GFP_ATOMIC); | ||
752 | if (!bcbearer || !bclink) { | ||
753 | nomem: | ||
754 | warn("Memory squeeze; Failed to create multicast link\n"); | ||
755 | kfree(bcbearer); | ||
756 | bcbearer = NULL; | ||
757 | kfree(bclink); | ||
758 | bclink = NULL; | ||
759 | return -ENOMEM; | ||
760 | } | ||
761 | |||
762 | memset(bcbearer, 0, sizeof(struct bcbearer)); | ||
763 | INIT_LIST_HEAD(&bcbearer->bearer.cong_links); | ||
764 | bcbearer->bearer.media = &bcbearer->media; | ||
765 | bcbearer->media.send_msg = bcbearer_send; | ||
766 | sprintf(bcbearer->media.name, "tipc-multicast"); | ||
767 | |||
768 | bcl = &bclink->link; | ||
769 | memset(bclink, 0, sizeof(struct bclink)); | ||
770 | INIT_LIST_HEAD(&bcl->waiting_ports); | ||
771 | bcl->next_out_no = 1; | ||
772 | bclink->node.lock = SPIN_LOCK_UNLOCKED; | ||
773 | bcl->owner = &bclink->node; | ||
774 | bcl->max_pkt = MAX_PKT_DEFAULT_MCAST; | ||
775 | link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); | ||
776 | bcl->b_ptr = &bcbearer->bearer; | ||
777 | bcl->state = WORKING_WORKING; | ||
778 | sprintf(bcl->name, bc_link_name); | ||
779 | |||
780 | if (BCLINK_LOG_BUF_SIZE) { | ||
781 | char *pb = kmalloc(BCLINK_LOG_BUF_SIZE, GFP_ATOMIC); | ||
782 | |||
783 | if (!pb) | ||
784 | goto nomem; | ||
785 | printbuf_init(&bcl->print_buf, pb, BCLINK_LOG_BUF_SIZE); | ||
786 | } | ||
787 | |||
788 | return TIPC_OK; | ||
789 | } | ||
790 | |||
791 | void bclink_stop(void) | ||
792 | { | ||
793 | spin_lock_bh(&bc_lock); | ||
794 | if (bcbearer) { | ||
795 | link_stop(bcl); | ||
796 | if (BCLINK_LOG_BUF_SIZE) | ||
797 | kfree(bcl->print_buf.buf); | ||
798 | bcl = NULL; | ||
799 | kfree(bclink); | ||
800 | bclink = NULL; | ||
801 | kfree(bcbearer); | ||
802 | bcbearer = NULL; | ||
803 | } | ||
804 | spin_unlock_bh(&bc_lock); | ||
805 | } | ||
806 | |||
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h new file mode 100644 index 000000000000..5430e524b4f9 --- /dev/null +++ b/net/tipc/bcast.h | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * net/tipc/bcast.h: Include file for TIPC broadcast code | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_BCAST_H | ||
38 | #define _TIPC_BCAST_H | ||
39 | |||
40 | #define MAX_NODES 4096 | ||
41 | #define WSIZE 32 | ||
42 | |||
43 | /** | ||
44 | * struct node_map - set of node identifiers | ||
45 | * @count: # of nodes in set | ||
46 | * @map: bitmap of node identifiers that are in the set | ||
47 | */ | ||
48 | |||
49 | struct node_map { | ||
50 | u32 count; | ||
51 | u32 map[MAX_NODES / WSIZE]; | ||
52 | }; | ||
53 | |||
54 | |||
55 | #define PLSIZE 32 | ||
56 | |||
57 | /** | ||
58 | * struct port_list - set of node local destination ports | ||
59 | * @count: # of ports in set (only valid for first entry in list) | ||
60 | * @next: pointer to next entry in list | ||
61 | * @ports: array of port references | ||
62 | */ | ||
63 | |||
64 | struct port_list { | ||
65 | int count; | ||
66 | struct port_list *next; | ||
67 | u32 ports[PLSIZE]; | ||
68 | }; | ||
69 | |||
70 | |||
71 | struct node; | ||
72 | |||
73 | extern char bc_link_name[]; | ||
74 | |||
75 | |||
76 | /** | ||
77 | * nmap_get - determine if node exists in a node map | ||
78 | */ | ||
79 | |||
80 | static inline int nmap_get(struct node_map *nm_ptr, u32 node) | ||
81 | { | ||
82 | int n = tipc_node(node); | ||
83 | int w = n / WSIZE; | ||
84 | int b = n % WSIZE; | ||
85 | |||
86 | return nm_ptr->map[w] & (1 << b); | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * nmap_add - add a node to a node map | ||
91 | */ | ||
92 | |||
93 | static inline void nmap_add(struct node_map *nm_ptr, u32 node) | ||
94 | { | ||
95 | int n = tipc_node(node); | ||
96 | int w = n / WSIZE; | ||
97 | u32 mask = (1 << (n % WSIZE)); | ||
98 | |||
99 | if ((nm_ptr->map[w] & mask) == 0) { | ||
100 | nm_ptr->count++; | ||
101 | nm_ptr->map[w] |= mask; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * nmap_remove - remove a node from a node map | ||
107 | */ | ||
108 | |||
109 | static inline void nmap_remove(struct node_map *nm_ptr, u32 node) | ||
110 | { | ||
111 | int n = tipc_node(node); | ||
112 | int w = n / WSIZE; | ||
113 | u32 mask = (1 << (n % WSIZE)); | ||
114 | |||
115 | if ((nm_ptr->map[w] & mask) != 0) { | ||
116 | nm_ptr->map[w] &= ~mask; | ||
117 | nm_ptr->count--; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | /** | ||
122 | * nmap_equal - test for equality of node maps | ||
123 | */ | ||
124 | |||
125 | static inline int nmap_equal(struct node_map *nm_a, struct node_map *nm_b) | ||
126 | { | ||
127 | return !memcmp(nm_a, nm_b, sizeof(*nm_a)); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * nmap_diff - find differences between node maps | ||
132 | * @nm_a: input node map A | ||
133 | * @nm_b: input node map B | ||
134 | * @nm_diff: output node map A-B (i.e. nodes of A that are not in B) | ||
135 | */ | ||
136 | |||
137 | static inline void nmap_diff(struct node_map *nm_a, struct node_map *nm_b, | ||
138 | struct node_map *nm_diff) | ||
139 | { | ||
140 | int stop = sizeof(nm_a->map) / sizeof(u32); | ||
141 | int w; | ||
142 | int b; | ||
143 | u32 map; | ||
144 | |||
145 | memset(nm_diff, 0, sizeof(*nm_diff)); | ||
146 | for (w = 0; w < stop; w++) { | ||
147 | map = nm_a->map[w] ^ (nm_a->map[w] & nm_b->map[w]); | ||
148 | nm_diff->map[w] = map; | ||
149 | if (map != 0) { | ||
150 | for (b = 0 ; b < WSIZE; b++) { | ||
151 | if (map & (1 << b)) | ||
152 | nm_diff->count++; | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | |||
158 | /** | ||
159 | * port_list_add - add a port to a port list, ensuring no duplicates | ||
160 | */ | ||
161 | |||
162 | static inline void port_list_add(struct port_list *pl_ptr, u32 port) | ||
163 | { | ||
164 | struct port_list *item = pl_ptr; | ||
165 | int i; | ||
166 | int item_sz = PLSIZE; | ||
167 | int cnt = pl_ptr->count; | ||
168 | |||
169 | for (; ; cnt -= item_sz, item = item->next) { | ||
170 | if (cnt < PLSIZE) | ||
171 | item_sz = cnt; | ||
172 | for (i = 0; i < item_sz; i++) | ||
173 | if (item->ports[i] == port) | ||
174 | return; | ||
175 | if (i < PLSIZE) { | ||
176 | item->ports[i] = port; | ||
177 | pl_ptr->count++; | ||
178 | return; | ||
179 | } | ||
180 | if (!item->next) { | ||
181 | item->next = kmalloc(sizeof(*item), GFP_ATOMIC); | ||
182 | if (!item->next) { | ||
183 | warn("Memory squeeze: multicast destination port list is incomplete\n"); | ||
184 | return; | ||
185 | } | ||
186 | item->next->next = NULL; | ||
187 | } | ||
188 | } | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * port_list_free - free dynamically created entries in port_list chain | ||
193 | * | ||
194 | * Note: First item is on stack, so it doesn't need to be released | ||
195 | */ | ||
196 | |||
197 | static inline void port_list_free(struct port_list *pl_ptr) | ||
198 | { | ||
199 | struct port_list *item; | ||
200 | struct port_list *next; | ||
201 | |||
202 | for (item = pl_ptr->next; item; item = next) { | ||
203 | next = item->next; | ||
204 | kfree(item); | ||
205 | } | ||
206 | } | ||
207 | |||
208 | |||
209 | int bclink_init(void); | ||
210 | void bclink_stop(void); | ||
211 | void bclink_acknowledge(struct node *n_ptr, u32 acked); | ||
212 | int bclink_send_msg(struct sk_buff *buf); | ||
213 | void bclink_recv_pkt(struct sk_buff *buf); | ||
214 | u32 bclink_get_last_sent(void); | ||
215 | u32 bclink_acks_missing(struct node *n_ptr); | ||
216 | void bclink_check_gap(struct node *n_ptr, u32 seqno); | ||
217 | int bclink_stats(char *stats_buf, const u32 buf_size); | ||
218 | int bclink_reset_stats(void); | ||
219 | int bclink_set_queue_limits(u32 limit); | ||
220 | void bcbearer_sort(void); | ||
221 | void bcbearer_push(void); | ||
222 | |||
223 | #endif | ||
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c new file mode 100644 index 000000000000..3dd19fdc5a2c --- /dev/null +++ b/net/tipc/bearer.c | |||
@@ -0,0 +1,692 @@ | |||
1 | /* | ||
2 | * net/tipc/bearer.c: TIPC bearer code | ||
3 | * | ||
4 | * Copyright (c) 1996-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "config.h" | ||
39 | #include "dbg.h" | ||
40 | #include "bearer.h" | ||
41 | #include "link.h" | ||
42 | #include "port.h" | ||
43 | #include "discover.h" | ||
44 | #include "bcast.h" | ||
45 | |||
46 | #define MAX_ADDR_STR 32 | ||
47 | |||
48 | static struct media *media_list = 0; | ||
49 | static u32 media_count = 0; | ||
50 | |||
51 | struct bearer *bearers = 0; | ||
52 | |||
53 | /** | ||
54 | * media_name_valid - validate media name | ||
55 | * | ||
56 | * Returns 1 if media name is valid, otherwise 0. | ||
57 | */ | ||
58 | |||
59 | static int media_name_valid(const char *name) | ||
60 | { | ||
61 | u32 len; | ||
62 | |||
63 | len = strlen(name); | ||
64 | if ((len + 1) > TIPC_MAX_MEDIA_NAME) | ||
65 | return 0; | ||
66 | return (strspn(name, tipc_alphabet) == len); | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | * media_find - locates specified media object by name | ||
71 | */ | ||
72 | |||
73 | static struct media *media_find(const char *name) | ||
74 | { | ||
75 | struct media *m_ptr; | ||
76 | u32 i; | ||
77 | |||
78 | for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) { | ||
79 | if (!strcmp(m_ptr->name, name)) | ||
80 | return m_ptr; | ||
81 | } | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * tipc_register_media - register a media type | ||
87 | * | ||
88 | * Bearers for this media type must be activated separately at a later stage. | ||
89 | */ | ||
90 | |||
91 | int tipc_register_media(u32 media_type, | ||
92 | char *name, | ||
93 | int (*enable)(struct tipc_bearer *), | ||
94 | void (*disable)(struct tipc_bearer *), | ||
95 | int (*send_msg)(struct sk_buff *, | ||
96 | struct tipc_bearer *, | ||
97 | struct tipc_media_addr *), | ||
98 | char *(*addr2str)(struct tipc_media_addr *a, | ||
99 | char *str_buf, int str_size), | ||
100 | struct tipc_media_addr *bcast_addr, | ||
101 | const u32 bearer_priority, | ||
102 | const u32 link_tolerance, /* [ms] */ | ||
103 | const u32 send_window_limit) | ||
104 | { | ||
105 | struct media *m_ptr; | ||
106 | u32 media_id; | ||
107 | u32 i; | ||
108 | int res = -EINVAL; | ||
109 | |||
110 | write_lock_bh(&net_lock); | ||
111 | if (!media_list) | ||
112 | goto exit; | ||
113 | |||
114 | if (!media_name_valid(name)) { | ||
115 | warn("Media registration error: illegal name <%s>\n", name); | ||
116 | goto exit; | ||
117 | } | ||
118 | if (!bcast_addr) { | ||
119 | warn("Media registration error: no broadcast address supplied\n"); | ||
120 | goto exit; | ||
121 | } | ||
122 | if (bearer_priority >= TIPC_NUM_LINK_PRI) { | ||
123 | warn("Media registration error: priority %u\n", bearer_priority); | ||
124 | goto exit; | ||
125 | } | ||
126 | if ((link_tolerance < TIPC_MIN_LINK_TOL) || | ||
127 | (link_tolerance > TIPC_MAX_LINK_TOL)) { | ||
128 | warn("Media registration error: tolerance %u\n", link_tolerance); | ||
129 | goto exit; | ||
130 | } | ||
131 | |||
132 | media_id = media_count++; | ||
133 | if (media_id >= MAX_MEDIA) { | ||
134 | warn("Attempt to register more than %u media\n", MAX_MEDIA); | ||
135 | media_count--; | ||
136 | goto exit; | ||
137 | } | ||
138 | for (i = 0; i < media_id; i++) { | ||
139 | if (media_list[i].type_id == media_type) { | ||
140 | warn("Attempt to register second media with type %u\n", | ||
141 | media_type); | ||
142 | media_count--; | ||
143 | goto exit; | ||
144 | } | ||
145 | if (!strcmp(name, media_list[i].name)) { | ||
146 | warn("Attempt to re-register media name <%s>\n", name); | ||
147 | media_count--; | ||
148 | goto exit; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | m_ptr = &media_list[media_id]; | ||
153 | m_ptr->type_id = media_type; | ||
154 | m_ptr->send_msg = send_msg; | ||
155 | m_ptr->enable_bearer = enable; | ||
156 | m_ptr->disable_bearer = disable; | ||
157 | m_ptr->addr2str = addr2str; | ||
158 | memcpy(&m_ptr->bcast_addr, bcast_addr, sizeof(*bcast_addr)); | ||
159 | m_ptr->bcast = 1; | ||
160 | strcpy(m_ptr->name, name); | ||
161 | m_ptr->priority = bearer_priority; | ||
162 | m_ptr->tolerance = link_tolerance; | ||
163 | m_ptr->window = send_window_limit; | ||
164 | dbg("Media <%s> registered\n", name); | ||
165 | res = 0; | ||
166 | exit: | ||
167 | write_unlock_bh(&net_lock); | ||
168 | return res; | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * media_addr_printf - record media address in print buffer | ||
173 | */ | ||
174 | |||
175 | void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a) | ||
176 | { | ||
177 | struct media *m_ptr; | ||
178 | u32 media_type; | ||
179 | u32 i; | ||
180 | |||
181 | media_type = ntohl(a->type); | ||
182 | for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) { | ||
183 | if (m_ptr->type_id == media_type) | ||
184 | break; | ||
185 | } | ||
186 | |||
187 | if ((i < media_count) && (m_ptr->addr2str != NULL)) { | ||
188 | char addr_str[MAX_ADDR_STR]; | ||
189 | |||
190 | tipc_printf(pb, "%s(%s) ", m_ptr->name, | ||
191 | m_ptr->addr2str(a, addr_str, sizeof(addr_str))); | ||
192 | } else { | ||
193 | unchar *addr = (unchar *)&a->dev_addr; | ||
194 | |||
195 | tipc_printf(pb, "UNKNOWN(%u):", media_type); | ||
196 | for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) { | ||
197 | tipc_printf(pb, "%02x ", addr[i]); | ||
198 | } | ||
199 | } | ||
200 | } | ||
201 | |||
202 | /** | ||
203 | * media_get_names - record names of registered media in buffer | ||
204 | */ | ||
205 | |||
206 | struct sk_buff *media_get_names(void) | ||
207 | { | ||
208 | struct sk_buff *buf; | ||
209 | struct media *m_ptr; | ||
210 | int i; | ||
211 | |||
212 | buf = cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME)); | ||
213 | if (!buf) | ||
214 | return NULL; | ||
215 | |||
216 | read_lock_bh(&net_lock); | ||
217 | for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) { | ||
218 | cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name, | ||
219 | strlen(m_ptr->name) + 1); | ||
220 | } | ||
221 | read_unlock_bh(&net_lock); | ||
222 | return buf; | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * bearer_name_validate - validate & (optionally) deconstruct bearer name | ||
227 | * @name - ptr to bearer name string | ||
228 | * @name_parts - ptr to area for bearer name components (or NULL if not needed) | ||
229 | * | ||
230 | * Returns 1 if bearer name is valid, otherwise 0. | ||
231 | */ | ||
232 | |||
233 | static int bearer_name_validate(const char *name, | ||
234 | struct bearer_name *name_parts) | ||
235 | { | ||
236 | char name_copy[TIPC_MAX_BEARER_NAME]; | ||
237 | char *media_name; | ||
238 | char *if_name; | ||
239 | u32 media_len; | ||
240 | u32 if_len; | ||
241 | |||
242 | /* copy bearer name & ensure length is OK */ | ||
243 | |||
244 | name_copy[TIPC_MAX_BEARER_NAME - 1] = 0; | ||
245 | /* need above in case non-Posix strncpy() doesn't pad with nulls */ | ||
246 | strncpy(name_copy, name, TIPC_MAX_BEARER_NAME); | ||
247 | if (name_copy[TIPC_MAX_BEARER_NAME - 1] != 0) | ||
248 | return 0; | ||
249 | |||
250 | /* ensure all component parts of bearer name are present */ | ||
251 | |||
252 | media_name = name_copy; | ||
253 | if ((if_name = strchr(media_name, ':')) == NULL) | ||
254 | return 0; | ||
255 | *(if_name++) = 0; | ||
256 | media_len = if_name - media_name; | ||
257 | if_len = strlen(if_name) + 1; | ||
258 | |||
259 | /* validate component parts of bearer name */ | ||
260 | |||
261 | if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) || | ||
262 | (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME) || | ||
263 | (strspn(media_name, tipc_alphabet) != (media_len - 1)) || | ||
264 | (strspn(if_name, tipc_alphabet) != (if_len - 1))) | ||
265 | return 0; | ||
266 | |||
267 | /* return bearer name components, if necessary */ | ||
268 | |||
269 | if (name_parts) { | ||
270 | strcpy(name_parts->media_name, media_name); | ||
271 | strcpy(name_parts->if_name, if_name); | ||
272 | } | ||
273 | return 1; | ||
274 | } | ||
275 | |||
276 | /** | ||
277 | * bearer_find - locates bearer object with matching bearer name | ||
278 | */ | ||
279 | |||
280 | static struct bearer *bearer_find(const char *name) | ||
281 | { | ||
282 | struct bearer *b_ptr; | ||
283 | u32 i; | ||
284 | |||
285 | for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) { | ||
286 | if (b_ptr->active && (!strcmp(b_ptr->publ.name, name))) | ||
287 | return b_ptr; | ||
288 | } | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | /** | ||
293 | * bearer_find - locates bearer object with matching interface name | ||
294 | */ | ||
295 | |||
296 | struct bearer *bearer_find_interface(const char *if_name) | ||
297 | { | ||
298 | struct bearer *b_ptr; | ||
299 | char *b_if_name; | ||
300 | u32 i; | ||
301 | |||
302 | for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) { | ||
303 | if (!b_ptr->active) | ||
304 | continue; | ||
305 | b_if_name = strchr(b_ptr->publ.name, ':') + 1; | ||
306 | if (!strcmp(b_if_name, if_name)) | ||
307 | return b_ptr; | ||
308 | } | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | /** | ||
313 | * bearer_get_names - record names of bearers in buffer | ||
314 | */ | ||
315 | |||
316 | struct sk_buff *bearer_get_names(void) | ||
317 | { | ||
318 | struct sk_buff *buf; | ||
319 | struct media *m_ptr; | ||
320 | struct bearer *b_ptr; | ||
321 | int i, j; | ||
322 | |||
323 | buf = cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME)); | ||
324 | if (!buf) | ||
325 | return NULL; | ||
326 | |||
327 | read_lock_bh(&net_lock); | ||
328 | for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) { | ||
329 | for (j = 0; j < MAX_BEARERS; j++) { | ||
330 | b_ptr = &bearers[j]; | ||
331 | if (b_ptr->active && (b_ptr->media == m_ptr)) { | ||
332 | cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, | ||
333 | b_ptr->publ.name, | ||
334 | strlen(b_ptr->publ.name) + 1); | ||
335 | } | ||
336 | } | ||
337 | } | ||
338 | read_unlock_bh(&net_lock); | ||
339 | return buf; | ||
340 | } | ||
341 | |||
342 | void bearer_add_dest(struct bearer *b_ptr, u32 dest) | ||
343 | { | ||
344 | nmap_add(&b_ptr->nodes, dest); | ||
345 | disc_update_link_req(b_ptr->link_req); | ||
346 | bcbearer_sort(); | ||
347 | } | ||
348 | |||
349 | void bearer_remove_dest(struct bearer *b_ptr, u32 dest) | ||
350 | { | ||
351 | nmap_remove(&b_ptr->nodes, dest); | ||
352 | disc_update_link_req(b_ptr->link_req); | ||
353 | bcbearer_sort(); | ||
354 | } | ||
355 | |||
356 | /* | ||
357 | * bearer_push(): Resolve bearer congestion. Force the waiting | ||
358 | * links to push out their unsent packets, one packet per link | ||
359 | * per iteration, until all packets are gone or congestion reoccurs. | ||
360 | * 'net_lock' is read_locked when this function is called | ||
361 | * bearer.lock must be taken before calling | ||
362 | * Returns binary true(1) ore false(0) | ||
363 | */ | ||
364 | static int bearer_push(struct bearer *b_ptr) | ||
365 | { | ||
366 | u32 res = TIPC_OK; | ||
367 | struct link *ln, *tln; | ||
368 | |||
369 | if (b_ptr->publ.blocked) | ||
370 | return 0; | ||
371 | |||
372 | while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) { | ||
373 | list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) { | ||
374 | res = link_push_packet(ln); | ||
375 | if (res == PUSH_FAILED) | ||
376 | break; | ||
377 | if (res == PUSH_FINISHED) | ||
378 | list_move_tail(&ln->link_list, &b_ptr->links); | ||
379 | } | ||
380 | } | ||
381 | return list_empty(&b_ptr->cong_links); | ||
382 | } | ||
383 | |||
384 | void bearer_lock_push(struct bearer *b_ptr) | ||
385 | { | ||
386 | int res; | ||
387 | |||
388 | spin_lock_bh(&b_ptr->publ.lock); | ||
389 | res = bearer_push(b_ptr); | ||
390 | spin_unlock_bh(&b_ptr->publ.lock); | ||
391 | if (res) | ||
392 | bcbearer_push(); | ||
393 | } | ||
394 | |||
395 | |||
396 | /* | ||
397 | * Interrupt enabling new requests after bearer congestion or blocking: | ||
398 | * See bearer_send(). | ||
399 | */ | ||
400 | void tipc_continue(struct tipc_bearer *tb_ptr) | ||
401 | { | ||
402 | struct bearer *b_ptr = (struct bearer *)tb_ptr; | ||
403 | |||
404 | spin_lock_bh(&b_ptr->publ.lock); | ||
405 | b_ptr->continue_count++; | ||
406 | if (!list_empty(&b_ptr->cong_links)) | ||
407 | k_signal((Handler)bearer_lock_push, (unsigned long)b_ptr); | ||
408 | b_ptr->publ.blocked = 0; | ||
409 | spin_unlock_bh(&b_ptr->publ.lock); | ||
410 | } | ||
411 | |||
412 | /* | ||
413 | * Schedule link for sending of messages after the bearer | ||
414 | * has been deblocked by 'continue()'. This method is called | ||
415 | * when somebody tries to send a message via this link while | ||
416 | * the bearer is congested. 'net_lock' is in read_lock here | ||
417 | * bearer.lock is busy | ||
418 | */ | ||
419 | |||
420 | static void bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr) | ||
421 | { | ||
422 | list_move_tail(&l_ptr->link_list, &b_ptr->cong_links); | ||
423 | } | ||
424 | |||
425 | /* | ||
426 | * Schedule link for sending of messages after the bearer | ||
427 | * has been deblocked by 'continue()'. This method is called | ||
428 | * when somebody tries to send a message via this link while | ||
429 | * the bearer is congested. 'net_lock' is in read_lock here, | ||
430 | * bearer.lock is free | ||
431 | */ | ||
432 | |||
433 | void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr) | ||
434 | { | ||
435 | spin_lock_bh(&b_ptr->publ.lock); | ||
436 | bearer_schedule_unlocked(b_ptr, l_ptr); | ||
437 | spin_unlock_bh(&b_ptr->publ.lock); | ||
438 | } | ||
439 | |||
440 | |||
441 | /* | ||
442 | * bearer_resolve_congestion(): Check if there is bearer congestion, | ||
443 | * and if there is, try to resolve it before returning. | ||
444 | * 'net_lock' is read_locked when this function is called | ||
445 | */ | ||
446 | int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr) | ||
447 | { | ||
448 | int res = 1; | ||
449 | |||
450 | if (list_empty(&b_ptr->cong_links)) | ||
451 | return 1; | ||
452 | spin_lock_bh(&b_ptr->publ.lock); | ||
453 | if (!bearer_push(b_ptr)) { | ||
454 | bearer_schedule_unlocked(b_ptr, l_ptr); | ||
455 | res = 0; | ||
456 | } | ||
457 | spin_unlock_bh(&b_ptr->publ.lock); | ||
458 | return res; | ||
459 | } | ||
460 | |||
461 | |||
462 | /** | ||
463 | * tipc_enable_bearer - enable bearer with the given name | ||
464 | */ | ||
465 | |||
466 | int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority) | ||
467 | { | ||
468 | struct bearer *b_ptr; | ||
469 | struct media *m_ptr; | ||
470 | struct bearer_name b_name; | ||
471 | char addr_string[16]; | ||
472 | u32 bearer_id; | ||
473 | u32 with_this_prio; | ||
474 | u32 i; | ||
475 | int res = -EINVAL; | ||
476 | |||
477 | if (tipc_mode != TIPC_NET_MODE) | ||
478 | return -ENOPROTOOPT; | ||
479 | if (!bearer_name_validate(name, &b_name) || | ||
480 | !addr_domain_valid(bcast_scope) || | ||
481 | !in_scope(bcast_scope, tipc_own_addr) || | ||
482 | (priority > TIPC_NUM_LINK_PRI)) | ||
483 | return -EINVAL; | ||
484 | |||
485 | write_lock_bh(&net_lock); | ||
486 | if (!bearers) | ||
487 | goto failed; | ||
488 | |||
489 | m_ptr = media_find(b_name.media_name); | ||
490 | if (!m_ptr) { | ||
491 | warn("No media <%s>\n", b_name.media_name); | ||
492 | goto failed; | ||
493 | } | ||
494 | if (priority == TIPC_NUM_LINK_PRI) | ||
495 | priority = m_ptr->priority; | ||
496 | |||
497 | restart: | ||
498 | bearer_id = MAX_BEARERS; | ||
499 | with_this_prio = 1; | ||
500 | for (i = MAX_BEARERS; i-- != 0; ) { | ||
501 | if (!bearers[i].active) { | ||
502 | bearer_id = i; | ||
503 | continue; | ||
504 | } | ||
505 | if (!strcmp(name, bearers[i].publ.name)) { | ||
506 | warn("Bearer <%s> already enabled\n", name); | ||
507 | goto failed; | ||
508 | } | ||
509 | if ((bearers[i].priority == priority) && | ||
510 | (++with_this_prio > 2)) { | ||
511 | if (priority-- == 0) { | ||
512 | warn("Third bearer <%s> with priority %u, unable to lower to %u\n", | ||
513 | name, priority + 1, priority); | ||
514 | goto failed; | ||
515 | } | ||
516 | warn("Third bearer <%s> with priority %u, lowering to %u\n", | ||
517 | name, priority + 1, priority); | ||
518 | goto restart; | ||
519 | } | ||
520 | } | ||
521 | if (bearer_id >= MAX_BEARERS) { | ||
522 | warn("Attempt to enable more than %d bearers\n", MAX_BEARERS); | ||
523 | goto failed; | ||
524 | } | ||
525 | |||
526 | b_ptr = &bearers[bearer_id]; | ||
527 | memset(b_ptr, 0, sizeof(struct bearer)); | ||
528 | |||
529 | strcpy(b_ptr->publ.name, name); | ||
530 | res = m_ptr->enable_bearer(&b_ptr->publ); | ||
531 | if (res) { | ||
532 | warn("Failed to enable bearer <%s>\n", name); | ||
533 | goto failed; | ||
534 | } | ||
535 | |||
536 | b_ptr->identity = bearer_id; | ||
537 | b_ptr->media = m_ptr; | ||
538 | b_ptr->net_plane = bearer_id + 'A'; | ||
539 | b_ptr->active = 1; | ||
540 | b_ptr->detect_scope = bcast_scope; | ||
541 | b_ptr->priority = priority; | ||
542 | INIT_LIST_HEAD(&b_ptr->cong_links); | ||
543 | INIT_LIST_HEAD(&b_ptr->links); | ||
544 | if (m_ptr->bcast) { | ||
545 | b_ptr->link_req = disc_init_link_req(b_ptr, &m_ptr->bcast_addr, | ||
546 | bcast_scope, 2); | ||
547 | } | ||
548 | b_ptr->publ.lock = SPIN_LOCK_UNLOCKED; | ||
549 | write_unlock_bh(&net_lock); | ||
550 | info("Enabled bearer <%s>, discovery domain %s\n", | ||
551 | name, addr_string_fill(addr_string, bcast_scope)); | ||
552 | return 0; | ||
553 | failed: | ||
554 | write_unlock_bh(&net_lock); | ||
555 | return res; | ||
556 | } | ||
557 | |||
558 | /** | ||
559 | * tipc_block_bearer(): Block the bearer with the given name, | ||
560 | * and reset all its links | ||
561 | */ | ||
562 | |||
563 | int tipc_block_bearer(const char *name) | ||
564 | { | ||
565 | struct bearer *b_ptr = 0; | ||
566 | struct link *l_ptr; | ||
567 | struct link *temp_l_ptr; | ||
568 | |||
569 | if (tipc_mode != TIPC_NET_MODE) | ||
570 | return -ENOPROTOOPT; | ||
571 | |||
572 | read_lock_bh(&net_lock); | ||
573 | b_ptr = bearer_find(name); | ||
574 | if (!b_ptr) { | ||
575 | warn("Attempt to block unknown bearer <%s>\n", name); | ||
576 | read_unlock_bh(&net_lock); | ||
577 | return -EINVAL; | ||
578 | } | ||
579 | |||
580 | spin_lock_bh(&b_ptr->publ.lock); | ||
581 | b_ptr->publ.blocked = 1; | ||
582 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | ||
583 | struct node *n_ptr = l_ptr->owner; | ||
584 | |||
585 | spin_lock_bh(&n_ptr->lock); | ||
586 | link_reset(l_ptr); | ||
587 | spin_unlock_bh(&n_ptr->lock); | ||
588 | } | ||
589 | spin_unlock_bh(&b_ptr->publ.lock); | ||
590 | read_unlock_bh(&net_lock); | ||
591 | info("Blocked bearer <%s>\n", name); | ||
592 | return TIPC_OK; | ||
593 | } | ||
594 | |||
595 | /** | ||
596 | * bearer_disable - | ||
597 | * | ||
598 | * Note: This routine assumes caller holds net_lock. | ||
599 | */ | ||
600 | |||
601 | static int bearer_disable(const char *name) | ||
602 | { | ||
603 | struct bearer *b_ptr; | ||
604 | struct link *l_ptr; | ||
605 | struct link *temp_l_ptr; | ||
606 | |||
607 | if (tipc_mode != TIPC_NET_MODE) | ||
608 | return -ENOPROTOOPT; | ||
609 | |||
610 | b_ptr = bearer_find(name); | ||
611 | if (!b_ptr) { | ||
612 | warn("Attempt to disable unknown bearer <%s>\n", name); | ||
613 | return -EINVAL; | ||
614 | } | ||
615 | |||
616 | disc_stop_link_req(b_ptr->link_req); | ||
617 | spin_lock_bh(&b_ptr->publ.lock); | ||
618 | b_ptr->link_req = NULL; | ||
619 | b_ptr->publ.blocked = 1; | ||
620 | if (b_ptr->media->disable_bearer) { | ||
621 | spin_unlock_bh(&b_ptr->publ.lock); | ||
622 | write_unlock_bh(&net_lock); | ||
623 | b_ptr->media->disable_bearer(&b_ptr->publ); | ||
624 | write_lock_bh(&net_lock); | ||
625 | spin_lock_bh(&b_ptr->publ.lock); | ||
626 | } | ||
627 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | ||
628 | link_delete(l_ptr); | ||
629 | } | ||
630 | spin_unlock_bh(&b_ptr->publ.lock); | ||
631 | info("Disabled bearer <%s>\n", name); | ||
632 | memset(b_ptr, 0, sizeof(struct bearer)); | ||
633 | return TIPC_OK; | ||
634 | } | ||
635 | |||
636 | int tipc_disable_bearer(const char *name) | ||
637 | { | ||
638 | int res; | ||
639 | |||
640 | write_lock_bh(&net_lock); | ||
641 | res = bearer_disable(name); | ||
642 | write_unlock_bh(&net_lock); | ||
643 | return res; | ||
644 | } | ||
645 | |||
646 | |||
647 | |||
648 | int bearer_init(void) | ||
649 | { | ||
650 | int res; | ||
651 | |||
652 | write_lock_bh(&net_lock); | ||
653 | bearers = kmalloc(MAX_BEARERS * sizeof(struct bearer), GFP_ATOMIC); | ||
654 | media_list = kmalloc(MAX_MEDIA * sizeof(struct media), GFP_ATOMIC); | ||
655 | if (bearers && media_list) { | ||
656 | memset(bearers, 0, MAX_BEARERS * sizeof(struct bearer)); | ||
657 | memset(media_list, 0, MAX_MEDIA * sizeof(struct media)); | ||
658 | res = TIPC_OK; | ||
659 | } else { | ||
660 | kfree(bearers); | ||
661 | kfree(media_list); | ||
662 | bearers = 0; | ||
663 | media_list = 0; | ||
664 | res = -ENOMEM; | ||
665 | } | ||
666 | write_unlock_bh(&net_lock); | ||
667 | return res; | ||
668 | } | ||
669 | |||
670 | void bearer_stop(void) | ||
671 | { | ||
672 | u32 i; | ||
673 | |||
674 | if (!bearers) | ||
675 | return; | ||
676 | |||
677 | for (i = 0; i < MAX_BEARERS; i++) { | ||
678 | if (bearers[i].active) | ||
679 | bearers[i].publ.blocked = 1; | ||
680 | } | ||
681 | for (i = 0; i < MAX_BEARERS; i++) { | ||
682 | if (bearers[i].active) | ||
683 | bearer_disable(bearers[i].publ.name); | ||
684 | } | ||
685 | kfree(bearers); | ||
686 | kfree(media_list); | ||
687 | bearers = 0; | ||
688 | media_list = 0; | ||
689 | media_count = 0; | ||
690 | } | ||
691 | |||
692 | |||
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h new file mode 100644 index 000000000000..21e63d3f0183 --- /dev/null +++ b/net/tipc/bearer.h | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * net/tipc/bearer.h: Include file for TIPC bearer code | ||
3 | * | ||
4 | * Copyright (c) 1996-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_BEARER_H | ||
38 | #define _TIPC_BEARER_H | ||
39 | |||
40 | #include <net/tipc/tipc_bearer.h> | ||
41 | #include "bcast.h" | ||
42 | |||
43 | #define MAX_BEARERS 8 | ||
44 | #define MAX_MEDIA 4 | ||
45 | |||
46 | |||
47 | /** | ||
48 | * struct media - TIPC media information available to internal users | ||
49 | * @send_msg: routine which handles buffer transmission | ||
50 | * @enable_bearer: routine which enables a bearer | ||
51 | * @disable_bearer: routine which disables a bearer | ||
52 | * @addr2str: routine which converts bearer's address to string form | ||
53 | * @bcast_addr: media address used in broadcasting | ||
54 | * @bcast: non-zero if media supports broadcasting [currently mandatory] | ||
55 | * @priority: default link (and bearer) priority | ||
56 | * @tolerance: default time (in ms) before declaring link failure | ||
57 | * @window: default window (in packets) before declaring link congestion | ||
58 | * @type_id: TIPC media identifier [defined in tipc_bearer.h] | ||
59 | * @name: media name | ||
60 | */ | ||
61 | |||
62 | struct media { | ||
63 | int (*send_msg)(struct sk_buff *buf, | ||
64 | struct tipc_bearer *b_ptr, | ||
65 | struct tipc_media_addr *dest); | ||
66 | int (*enable_bearer)(struct tipc_bearer *b_ptr); | ||
67 | void (*disable_bearer)(struct tipc_bearer *b_ptr); | ||
68 | char *(*addr2str)(struct tipc_media_addr *a, | ||
69 | char *str_buf, int str_size); | ||
70 | struct tipc_media_addr bcast_addr; | ||
71 | int bcast; | ||
72 | u32 priority; | ||
73 | u32 tolerance; | ||
74 | u32 window; | ||
75 | u32 type_id; | ||
76 | char name[TIPC_MAX_MEDIA_NAME]; | ||
77 | }; | ||
78 | |||
79 | /** | ||
80 | * struct bearer - TIPC bearer information available to internal users | ||
81 | * @publ: bearer information available to privileged users | ||
82 | * @media: ptr to media structure associated with bearer | ||
83 | * @priority: default link priority for bearer | ||
84 | * @detect_scope: network address mask used during automatic link creation | ||
85 | * @identity: array index of this bearer within TIPC bearer array | ||
86 | * @link_req: ptr to (optional) structure making periodic link setup requests | ||
87 | * @links: list of non-congested links associated with bearer | ||
88 | * @cong_links: list of congested links associated with bearer | ||
89 | * @continue_count: # of times bearer has resumed after congestion or blocking | ||
90 | * @active: non-zero if bearer structure is represents a bearer | ||
91 | * @net_plane: network plane ('A' through 'H') currently associated with bearer | ||
92 | * @nodes: indicates which nodes in cluster can be reached through bearer | ||
93 | */ | ||
94 | |||
95 | struct bearer { | ||
96 | struct tipc_bearer publ; | ||
97 | struct media *media; | ||
98 | u32 priority; | ||
99 | u32 detect_scope; | ||
100 | u32 identity; | ||
101 | struct link_req *link_req; | ||
102 | struct list_head links; | ||
103 | struct list_head cong_links; | ||
104 | u32 continue_count; | ||
105 | int active; | ||
106 | char net_plane; | ||
107 | struct node_map nodes; | ||
108 | }; | ||
109 | |||
110 | struct bearer_name { | ||
111 | char media_name[TIPC_MAX_MEDIA_NAME]; | ||
112 | char if_name[TIPC_MAX_IF_NAME]; | ||
113 | }; | ||
114 | |||
115 | struct link; | ||
116 | |||
117 | extern struct bearer *bearers; | ||
118 | |||
119 | void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a); | ||
120 | struct sk_buff *media_get_names(void); | ||
121 | |||
122 | struct sk_buff *bearer_get_names(void); | ||
123 | void bearer_add_dest(struct bearer *b_ptr, u32 dest); | ||
124 | void bearer_remove_dest(struct bearer *b_ptr, u32 dest); | ||
125 | void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr); | ||
126 | struct bearer *bearer_find_interface(const char *if_name); | ||
127 | int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr); | ||
128 | int bearer_init(void); | ||
129 | void bearer_stop(void); | ||
130 | int bearer_broadcast(struct sk_buff *buf, struct tipc_bearer *b_ptr, | ||
131 | struct tipc_media_addr *dest); | ||
132 | void bearer_lock_push(struct bearer *b_ptr); | ||
133 | |||
134 | |||
135 | /** | ||
136 | * bearer_send- sends buffer to destination over bearer | ||
137 | * | ||
138 | * Returns true (1) if successful, or false (0) if unable to send | ||
139 | * | ||
140 | * IMPORTANT: | ||
141 | * The media send routine must not alter the buffer being passed in | ||
142 | * as it may be needed for later retransmission! | ||
143 | * | ||
144 | * If the media send routine returns a non-zero value (indicating that | ||
145 | * it was unable to send the buffer), it must: | ||
146 | * 1) mark the bearer as blocked, | ||
147 | * 2) call tipc_continue() once the bearer is able to send again. | ||
148 | * Media types that are unable to meet these two critera must ensure their | ||
149 | * send routine always returns success -- even if the buffer was not sent -- | ||
150 | * and let TIPC's link code deal with the undelivered message. | ||
151 | */ | ||
152 | |||
153 | static inline int bearer_send(struct bearer *b_ptr, struct sk_buff *buf, | ||
154 | struct tipc_media_addr *dest) | ||
155 | { | ||
156 | return !b_ptr->media->send_msg(buf, &b_ptr->publ, dest); | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * bearer_congested - determines if bearer is currently congested | ||
161 | */ | ||
162 | |||
163 | static inline int bearer_congested(struct bearer *b_ptr, struct link *l_ptr) | ||
164 | { | ||
165 | if (unlikely(b_ptr->publ.blocked)) | ||
166 | return 1; | ||
167 | if (likely(list_empty(&b_ptr->cong_links))) | ||
168 | return 0; | ||
169 | return !bearer_resolve_congestion(b_ptr, l_ptr); | ||
170 | } | ||
171 | |||
172 | #endif | ||
diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c new file mode 100644 index 000000000000..f0f7bac51d41 --- /dev/null +++ b/net/tipc/cluster.c | |||
@@ -0,0 +1,576 @@ | |||
1 | /* | ||
2 | * net/tipc/cluster.c: TIPC cluster management routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "cluster.h" | ||
39 | #include "addr.h" | ||
40 | #include "node_subscr.h" | ||
41 | #include "link.h" | ||
42 | #include "node.h" | ||
43 | #include "net.h" | ||
44 | #include "msg.h" | ||
45 | #include "bearer.h" | ||
46 | |||
47 | void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf, | ||
48 | u32 lower, u32 upper); | ||
49 | struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest); | ||
50 | |||
51 | struct node **local_nodes = 0; | ||
52 | struct node_map cluster_bcast_nodes = {0,{0,}}; | ||
53 | u32 highest_allowed_slave = 0; | ||
54 | |||
55 | struct cluster *cluster_create(u32 addr) | ||
56 | { | ||
57 | struct _zone *z_ptr; | ||
58 | struct cluster *c_ptr; | ||
59 | int max_nodes; | ||
60 | int alloc; | ||
61 | |||
62 | c_ptr = (struct cluster *)kmalloc(sizeof(*c_ptr), GFP_ATOMIC); | ||
63 | if (c_ptr == NULL) | ||
64 | return 0; | ||
65 | memset(c_ptr, 0, sizeof(*c_ptr)); | ||
66 | |||
67 | c_ptr->addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0); | ||
68 | if (in_own_cluster(addr)) | ||
69 | max_nodes = LOWEST_SLAVE + tipc_max_slaves; | ||
70 | else | ||
71 | max_nodes = tipc_max_nodes + 1; | ||
72 | alloc = sizeof(void *) * (max_nodes + 1); | ||
73 | c_ptr->nodes = (struct node **)kmalloc(alloc, GFP_ATOMIC); | ||
74 | if (c_ptr->nodes == NULL) { | ||
75 | kfree(c_ptr); | ||
76 | return 0; | ||
77 | } | ||
78 | memset(c_ptr->nodes, 0, alloc); | ||
79 | if (in_own_cluster(addr)) | ||
80 | local_nodes = c_ptr->nodes; | ||
81 | c_ptr->highest_slave = LOWEST_SLAVE - 1; | ||
82 | c_ptr->highest_node = 0; | ||
83 | |||
84 | z_ptr = zone_find(tipc_zone(addr)); | ||
85 | if (z_ptr == NULL) { | ||
86 | z_ptr = zone_create(addr); | ||
87 | } | ||
88 | if (z_ptr != NULL) { | ||
89 | zone_attach_cluster(z_ptr, c_ptr); | ||
90 | c_ptr->owner = z_ptr; | ||
91 | } | ||
92 | else { | ||
93 | kfree(c_ptr); | ||
94 | c_ptr = 0; | ||
95 | } | ||
96 | |||
97 | return c_ptr; | ||
98 | } | ||
99 | |||
100 | void cluster_delete(struct cluster *c_ptr) | ||
101 | { | ||
102 | u32 n_num; | ||
103 | |||
104 | if (!c_ptr) | ||
105 | return; | ||
106 | for (n_num = 1; n_num <= c_ptr->highest_node; n_num++) { | ||
107 | node_delete(c_ptr->nodes[n_num]); | ||
108 | } | ||
109 | for (n_num = LOWEST_SLAVE; n_num <= c_ptr->highest_slave; n_num++) { | ||
110 | node_delete(c_ptr->nodes[n_num]); | ||
111 | } | ||
112 | kfree(c_ptr->nodes); | ||
113 | kfree(c_ptr); | ||
114 | } | ||
115 | |||
116 | u32 cluster_next_node(struct cluster *c_ptr, u32 addr) | ||
117 | { | ||
118 | struct node *n_ptr; | ||
119 | u32 n_num = tipc_node(addr) + 1; | ||
120 | |||
121 | if (!c_ptr) | ||
122 | return addr; | ||
123 | for (; n_num <= c_ptr->highest_node; n_num++) { | ||
124 | n_ptr = c_ptr->nodes[n_num]; | ||
125 | if (n_ptr && node_has_active_links(n_ptr)) | ||
126 | return n_ptr->addr; | ||
127 | } | ||
128 | for (n_num = 1; n_num < tipc_node(addr); n_num++) { | ||
129 | n_ptr = c_ptr->nodes[n_num]; | ||
130 | if (n_ptr && node_has_active_links(n_ptr)) | ||
131 | return n_ptr->addr; | ||
132 | } | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr) | ||
137 | { | ||
138 | u32 n_num = tipc_node(n_ptr->addr); | ||
139 | u32 max_n_num = tipc_max_nodes; | ||
140 | |||
141 | if (in_own_cluster(n_ptr->addr)) | ||
142 | max_n_num = highest_allowed_slave; | ||
143 | assert(n_num > 0); | ||
144 | assert(n_num <= max_n_num); | ||
145 | assert(c_ptr->nodes[n_num] == 0); | ||
146 | c_ptr->nodes[n_num] = n_ptr; | ||
147 | if (n_num > c_ptr->highest_node) | ||
148 | c_ptr->highest_node = n_num; | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * cluster_select_router - select router to a cluster | ||
153 | * | ||
154 | * Uses deterministic and fair algorithm. | ||
155 | */ | ||
156 | |||
157 | u32 cluster_select_router(struct cluster *c_ptr, u32 ref) | ||
158 | { | ||
159 | u32 n_num; | ||
160 | u32 ulim = c_ptr->highest_node; | ||
161 | u32 mask; | ||
162 | u32 tstart; | ||
163 | |||
164 | assert(!in_own_cluster(c_ptr->addr)); | ||
165 | if (!ulim) | ||
166 | return 0; | ||
167 | |||
168 | /* Start entry must be random */ | ||
169 | mask = tipc_max_nodes; | ||
170 | while (mask > ulim) | ||
171 | mask >>= 1; | ||
172 | tstart = ref & mask; | ||
173 | n_num = tstart; | ||
174 | |||
175 | /* Lookup upwards with wrap-around */ | ||
176 | do { | ||
177 | if (node_is_up(c_ptr->nodes[n_num])) | ||
178 | break; | ||
179 | } while (++n_num <= ulim); | ||
180 | if (n_num > ulim) { | ||
181 | n_num = 1; | ||
182 | do { | ||
183 | if (node_is_up(c_ptr->nodes[n_num])) | ||
184 | break; | ||
185 | } while (++n_num < tstart); | ||
186 | if (n_num == tstart) | ||
187 | return 0; | ||
188 | } | ||
189 | assert(n_num <= ulim); | ||
190 | return node_select_router(c_ptr->nodes[n_num], ref); | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * cluster_select_node - select destination node within a remote cluster | ||
195 | * | ||
196 | * Uses deterministic and fair algorithm. | ||
197 | */ | ||
198 | |||
199 | struct node *cluster_select_node(struct cluster *c_ptr, u32 selector) | ||
200 | { | ||
201 | u32 n_num; | ||
202 | u32 mask = tipc_max_nodes; | ||
203 | u32 start_entry; | ||
204 | |||
205 | assert(!in_own_cluster(c_ptr->addr)); | ||
206 | if (!c_ptr->highest_node) | ||
207 | return 0; | ||
208 | |||
209 | /* Start entry must be random */ | ||
210 | while (mask > c_ptr->highest_node) { | ||
211 | mask >>= 1; | ||
212 | } | ||
213 | start_entry = (selector & mask) ? selector & mask : 1u; | ||
214 | assert(start_entry <= c_ptr->highest_node); | ||
215 | |||
216 | /* Lookup upwards with wrap-around */ | ||
217 | for (n_num = start_entry; n_num <= c_ptr->highest_node; n_num++) { | ||
218 | if (node_has_active_links(c_ptr->nodes[n_num])) | ||
219 | return c_ptr->nodes[n_num]; | ||
220 | } | ||
221 | for (n_num = 1; n_num < start_entry; n_num++) { | ||
222 | if (node_has_active_links(c_ptr->nodes[n_num])) | ||
223 | return c_ptr->nodes[n_num]; | ||
224 | } | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * Routing table management: See description in node.c | ||
230 | */ | ||
231 | |||
232 | struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest) | ||
233 | { | ||
234 | u32 size = INT_H_SIZE + data_size; | ||
235 | struct sk_buff *buf = buf_acquire(size); | ||
236 | struct tipc_msg *msg; | ||
237 | |||
238 | if (buf) { | ||
239 | msg = buf_msg(buf); | ||
240 | memset((char *)msg, 0, size); | ||
241 | msg_init(msg, ROUTE_DISTRIBUTOR, 0, TIPC_OK, INT_H_SIZE, dest); | ||
242 | } | ||
243 | return buf; | ||
244 | } | ||
245 | |||
246 | void cluster_bcast_new_route(struct cluster *c_ptr, u32 dest, | ||
247 | u32 lower, u32 upper) | ||
248 | { | ||
249 | struct sk_buff *buf = cluster_prepare_routing_msg(0, c_ptr->addr); | ||
250 | struct tipc_msg *msg; | ||
251 | |||
252 | if (buf) { | ||
253 | msg = buf_msg(buf); | ||
254 | msg_set_remote_node(msg, dest); | ||
255 | msg_set_type(msg, ROUTE_ADDITION); | ||
256 | cluster_multicast(c_ptr, buf, lower, upper); | ||
257 | } else { | ||
258 | warn("Memory squeeze: broadcast of new route failed\n"); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | void cluster_bcast_lost_route(struct cluster *c_ptr, u32 dest, | ||
263 | u32 lower, u32 upper) | ||
264 | { | ||
265 | struct sk_buff *buf = cluster_prepare_routing_msg(0, c_ptr->addr); | ||
266 | struct tipc_msg *msg; | ||
267 | |||
268 | if (buf) { | ||
269 | msg = buf_msg(buf); | ||
270 | msg_set_remote_node(msg, dest); | ||
271 | msg_set_type(msg, ROUTE_REMOVAL); | ||
272 | cluster_multicast(c_ptr, buf, lower, upper); | ||
273 | } else { | ||
274 | warn("Memory squeeze: broadcast of lost route failed\n"); | ||
275 | } | ||
276 | } | ||
277 | |||
278 | void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest) | ||
279 | { | ||
280 | struct sk_buff *buf; | ||
281 | struct tipc_msg *msg; | ||
282 | u32 highest = c_ptr->highest_slave; | ||
283 | u32 n_num; | ||
284 | int send = 0; | ||
285 | |||
286 | assert(!is_slave(dest)); | ||
287 | assert(in_own_cluster(dest)); | ||
288 | assert(in_own_cluster(c_ptr->addr)); | ||
289 | if (highest <= LOWEST_SLAVE) | ||
290 | return; | ||
291 | buf = cluster_prepare_routing_msg(highest - LOWEST_SLAVE + 1, | ||
292 | c_ptr->addr); | ||
293 | if (buf) { | ||
294 | msg = buf_msg(buf); | ||
295 | msg_set_remote_node(msg, c_ptr->addr); | ||
296 | msg_set_type(msg, SLAVE_ROUTING_TABLE); | ||
297 | for (n_num = LOWEST_SLAVE; n_num <= highest; n_num++) { | ||
298 | if (c_ptr->nodes[n_num] && | ||
299 | node_has_active_links(c_ptr->nodes[n_num])) { | ||
300 | send = 1; | ||
301 | msg_set_dataoctet(msg, n_num); | ||
302 | } | ||
303 | } | ||
304 | if (send) | ||
305 | link_send(buf, dest, dest); | ||
306 | else | ||
307 | buf_discard(buf); | ||
308 | } else { | ||
309 | warn("Memory squeeze: broadcast of lost route failed\n"); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest) | ||
314 | { | ||
315 | struct sk_buff *buf; | ||
316 | struct tipc_msg *msg; | ||
317 | u32 highest = c_ptr->highest_node; | ||
318 | u32 n_num; | ||
319 | int send = 0; | ||
320 | |||
321 | if (in_own_cluster(c_ptr->addr)) | ||
322 | return; | ||
323 | assert(!is_slave(dest)); | ||
324 | assert(in_own_cluster(dest)); | ||
325 | highest = c_ptr->highest_node; | ||
326 | buf = cluster_prepare_routing_msg(highest + 1, c_ptr->addr); | ||
327 | if (buf) { | ||
328 | msg = buf_msg(buf); | ||
329 | msg_set_remote_node(msg, c_ptr->addr); | ||
330 | msg_set_type(msg, EXT_ROUTING_TABLE); | ||
331 | for (n_num = 1; n_num <= highest; n_num++) { | ||
332 | if (c_ptr->nodes[n_num] && | ||
333 | node_has_active_links(c_ptr->nodes[n_num])) { | ||
334 | send = 1; | ||
335 | msg_set_dataoctet(msg, n_num); | ||
336 | } | ||
337 | } | ||
338 | if (send) | ||
339 | link_send(buf, dest, dest); | ||
340 | else | ||
341 | buf_discard(buf); | ||
342 | } else { | ||
343 | warn("Memory squeeze: broadcast of external route failed\n"); | ||
344 | } | ||
345 | } | ||
346 | |||
347 | void cluster_send_local_routes(struct cluster *c_ptr, u32 dest) | ||
348 | { | ||
349 | struct sk_buff *buf; | ||
350 | struct tipc_msg *msg; | ||
351 | u32 highest = c_ptr->highest_node; | ||
352 | u32 n_num; | ||
353 | int send = 0; | ||
354 | |||
355 | assert(is_slave(dest)); | ||
356 | assert(in_own_cluster(c_ptr->addr)); | ||
357 | buf = cluster_prepare_routing_msg(highest, c_ptr->addr); | ||
358 | if (buf) { | ||
359 | msg = buf_msg(buf); | ||
360 | msg_set_remote_node(msg, c_ptr->addr); | ||
361 | msg_set_type(msg, LOCAL_ROUTING_TABLE); | ||
362 | for (n_num = 1; n_num <= highest; n_num++) { | ||
363 | if (c_ptr->nodes[n_num] && | ||
364 | node_has_active_links(c_ptr->nodes[n_num])) { | ||
365 | send = 1; | ||
366 | msg_set_dataoctet(msg, n_num); | ||
367 | } | ||
368 | } | ||
369 | if (send) | ||
370 | link_send(buf, dest, dest); | ||
371 | else | ||
372 | buf_discard(buf); | ||
373 | } else { | ||
374 | warn("Memory squeeze: broadcast of local route failed\n"); | ||
375 | } | ||
376 | } | ||
377 | |||
378 | void cluster_recv_routing_table(struct sk_buff *buf) | ||
379 | { | ||
380 | struct tipc_msg *msg = buf_msg(buf); | ||
381 | struct cluster *c_ptr; | ||
382 | struct node *n_ptr; | ||
383 | unchar *node_table; | ||
384 | u32 table_size; | ||
385 | u32 router; | ||
386 | u32 rem_node = msg_remote_node(msg); | ||
387 | u32 z_num; | ||
388 | u32 c_num; | ||
389 | u32 n_num; | ||
390 | |||
391 | c_ptr = cluster_find(rem_node); | ||
392 | if (!c_ptr) { | ||
393 | c_ptr = cluster_create(rem_node); | ||
394 | if (!c_ptr) { | ||
395 | buf_discard(buf); | ||
396 | return; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | node_table = buf->data + msg_hdr_sz(msg); | ||
401 | table_size = msg_size(msg) - msg_hdr_sz(msg); | ||
402 | router = msg_prevnode(msg); | ||
403 | z_num = tipc_zone(rem_node); | ||
404 | c_num = tipc_cluster(rem_node); | ||
405 | |||
406 | switch (msg_type(msg)) { | ||
407 | case LOCAL_ROUTING_TABLE: | ||
408 | assert(is_slave(tipc_own_addr)); | ||
409 | case EXT_ROUTING_TABLE: | ||
410 | for (n_num = 1; n_num < table_size; n_num++) { | ||
411 | if (node_table[n_num]) { | ||
412 | u32 addr = tipc_addr(z_num, c_num, n_num); | ||
413 | n_ptr = c_ptr->nodes[n_num]; | ||
414 | if (!n_ptr) { | ||
415 | n_ptr = node_create(addr); | ||
416 | } | ||
417 | if (n_ptr) | ||
418 | node_add_router(n_ptr, router); | ||
419 | } | ||
420 | } | ||
421 | break; | ||
422 | case SLAVE_ROUTING_TABLE: | ||
423 | assert(!is_slave(tipc_own_addr)); | ||
424 | assert(in_own_cluster(c_ptr->addr)); | ||
425 | for (n_num = 1; n_num < table_size; n_num++) { | ||
426 | if (node_table[n_num]) { | ||
427 | u32 slave_num = n_num + LOWEST_SLAVE; | ||
428 | u32 addr = tipc_addr(z_num, c_num, slave_num); | ||
429 | n_ptr = c_ptr->nodes[slave_num]; | ||
430 | if (!n_ptr) { | ||
431 | n_ptr = node_create(addr); | ||
432 | } | ||
433 | if (n_ptr) | ||
434 | node_add_router(n_ptr, router); | ||
435 | } | ||
436 | } | ||
437 | break; | ||
438 | case ROUTE_ADDITION: | ||
439 | if (!is_slave(tipc_own_addr)) { | ||
440 | assert(!in_own_cluster(c_ptr->addr) | ||
441 | || is_slave(rem_node)); | ||
442 | } else { | ||
443 | assert(in_own_cluster(c_ptr->addr) | ||
444 | && !is_slave(rem_node)); | ||
445 | } | ||
446 | n_ptr = c_ptr->nodes[tipc_node(rem_node)]; | ||
447 | if (!n_ptr) | ||
448 | n_ptr = node_create(rem_node); | ||
449 | if (n_ptr) | ||
450 | node_add_router(n_ptr, router); | ||
451 | break; | ||
452 | case ROUTE_REMOVAL: | ||
453 | if (!is_slave(tipc_own_addr)) { | ||
454 | assert(!in_own_cluster(c_ptr->addr) | ||
455 | || is_slave(rem_node)); | ||
456 | } else { | ||
457 | assert(in_own_cluster(c_ptr->addr) | ||
458 | && !is_slave(rem_node)); | ||
459 | } | ||
460 | n_ptr = c_ptr->nodes[tipc_node(rem_node)]; | ||
461 | if (n_ptr) | ||
462 | node_remove_router(n_ptr, router); | ||
463 | break; | ||
464 | default: | ||
465 | assert(!"Illegal routing manager message received\n"); | ||
466 | } | ||
467 | buf_discard(buf); | ||
468 | } | ||
469 | |||
470 | void cluster_remove_as_router(struct cluster *c_ptr, u32 router) | ||
471 | { | ||
472 | u32 start_entry; | ||
473 | u32 tstop; | ||
474 | u32 n_num; | ||
475 | |||
476 | if (is_slave(router)) | ||
477 | return; /* Slave nodes can not be routers */ | ||
478 | |||
479 | if (in_own_cluster(c_ptr->addr)) { | ||
480 | start_entry = LOWEST_SLAVE; | ||
481 | tstop = c_ptr->highest_slave; | ||
482 | } else { | ||
483 | start_entry = 1; | ||
484 | tstop = c_ptr->highest_node; | ||
485 | } | ||
486 | |||
487 | for (n_num = start_entry; n_num <= tstop; n_num++) { | ||
488 | if (c_ptr->nodes[n_num]) { | ||
489 | node_remove_router(c_ptr->nodes[n_num], router); | ||
490 | } | ||
491 | } | ||
492 | } | ||
493 | |||
494 | /** | ||
495 | * cluster_multicast - multicast message to local nodes | ||
496 | */ | ||
497 | |||
498 | void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf, | ||
499 | u32 lower, u32 upper) | ||
500 | { | ||
501 | struct sk_buff *buf_copy; | ||
502 | struct node *n_ptr; | ||
503 | u32 n_num; | ||
504 | u32 tstop; | ||
505 | |||
506 | assert(lower <= upper); | ||
507 | assert(((lower >= 1) && (lower <= tipc_max_nodes)) || | ||
508 | ((lower >= LOWEST_SLAVE) && (lower <= highest_allowed_slave))); | ||
509 | assert(((upper >= 1) && (upper <= tipc_max_nodes)) || | ||
510 | ((upper >= LOWEST_SLAVE) && (upper <= highest_allowed_slave))); | ||
511 | assert(in_own_cluster(c_ptr->addr)); | ||
512 | |||
513 | tstop = is_slave(upper) ? c_ptr->highest_slave : c_ptr->highest_node; | ||
514 | if (tstop > upper) | ||
515 | tstop = upper; | ||
516 | for (n_num = lower; n_num <= tstop; n_num++) { | ||
517 | n_ptr = c_ptr->nodes[n_num]; | ||
518 | if (n_ptr && node_has_active_links(n_ptr)) { | ||
519 | buf_copy = skb_copy(buf, GFP_ATOMIC); | ||
520 | if (buf_copy == NULL) | ||
521 | break; | ||
522 | msg_set_destnode(buf_msg(buf_copy), n_ptr->addr); | ||
523 | link_send(buf_copy, n_ptr->addr, n_ptr->addr); | ||
524 | } | ||
525 | } | ||
526 | buf_discard(buf); | ||
527 | } | ||
528 | |||
529 | /** | ||
530 | * cluster_broadcast - broadcast message to all nodes within cluster | ||
531 | */ | ||
532 | |||
533 | void cluster_broadcast(struct sk_buff *buf) | ||
534 | { | ||
535 | struct sk_buff *buf_copy; | ||
536 | struct cluster *c_ptr; | ||
537 | struct node *n_ptr; | ||
538 | u32 n_num; | ||
539 | u32 tstart; | ||
540 | u32 tstop; | ||
541 | u32 node_type; | ||
542 | |||
543 | if (tipc_mode == TIPC_NET_MODE) { | ||
544 | c_ptr = cluster_find(tipc_own_addr); | ||
545 | assert(in_own_cluster(c_ptr->addr)); /* For now */ | ||
546 | |||
547 | /* Send to standard nodes, then repeat loop sending to slaves */ | ||
548 | tstart = 1; | ||
549 | tstop = c_ptr->highest_node; | ||
550 | for (node_type = 1; node_type <= 2; node_type++) { | ||
551 | for (n_num = tstart; n_num <= tstop; n_num++) { | ||
552 | n_ptr = c_ptr->nodes[n_num]; | ||
553 | if (n_ptr && node_has_active_links(n_ptr)) { | ||
554 | buf_copy = skb_copy(buf, GFP_ATOMIC); | ||
555 | if (buf_copy == NULL) | ||
556 | goto exit; | ||
557 | msg_set_destnode(buf_msg(buf_copy), | ||
558 | n_ptr->addr); | ||
559 | link_send(buf_copy, n_ptr->addr, | ||
560 | n_ptr->addr); | ||
561 | } | ||
562 | } | ||
563 | tstart = LOWEST_SLAVE; | ||
564 | tstop = c_ptr->highest_slave; | ||
565 | } | ||
566 | } | ||
567 | exit: | ||
568 | buf_discard(buf); | ||
569 | } | ||
570 | |||
571 | int cluster_init(void) | ||
572 | { | ||
573 | highest_allowed_slave = LOWEST_SLAVE + tipc_max_slaves; | ||
574 | return cluster_create(tipc_own_addr) ? TIPC_OK : -ENOMEM; | ||
575 | } | ||
576 | |||
diff --git a/net/tipc/cluster.h b/net/tipc/cluster.h new file mode 100644 index 000000000000..1ffb095991df --- /dev/null +++ b/net/tipc/cluster.h | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * net/tipc/cluster.h: Include file for TIPC cluster management routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_CLUSTER_H | ||
38 | #define _TIPC_CLUSTER_H | ||
39 | |||
40 | #include "addr.h" | ||
41 | #include "zone.h" | ||
42 | |||
43 | #define LOWEST_SLAVE 2048u | ||
44 | |||
45 | /** | ||
46 | * struct cluster - TIPC cluster structure | ||
47 | * @addr: network address of cluster | ||
48 | * @owner: pointer to zone that cluster belongs to | ||
49 | * @nodes: array of pointers to all nodes within cluster | ||
50 | * @highest_node: id of highest numbered node within cluster | ||
51 | * @highest_slave: (used for secondary node support) | ||
52 | */ | ||
53 | |||
54 | struct cluster { | ||
55 | u32 addr; | ||
56 | struct _zone *owner; | ||
57 | struct node **nodes; | ||
58 | u32 highest_node; | ||
59 | u32 highest_slave; | ||
60 | }; | ||
61 | |||
62 | |||
63 | extern struct node **local_nodes; | ||
64 | extern u32 highest_allowed_slave; | ||
65 | extern struct node_map cluster_bcast_nodes; | ||
66 | |||
67 | void cluster_remove_as_router(struct cluster *c_ptr, u32 router); | ||
68 | void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest); | ||
69 | struct node *cluster_select_node(struct cluster *c_ptr, u32 selector); | ||
70 | u32 cluster_select_router(struct cluster *c_ptr, u32 ref); | ||
71 | void cluster_recv_routing_table(struct sk_buff *buf); | ||
72 | struct cluster *cluster_create(u32 addr); | ||
73 | void cluster_delete(struct cluster *c_ptr); | ||
74 | void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr); | ||
75 | void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest); | ||
76 | void cluster_broadcast(struct sk_buff *buf); | ||
77 | int cluster_init(void); | ||
78 | u32 cluster_next_node(struct cluster *c_ptr, u32 addr); | ||
79 | void cluster_bcast_new_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi); | ||
80 | void cluster_send_local_routes(struct cluster *c_ptr, u32 dest); | ||
81 | void cluster_bcast_lost_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi); | ||
82 | |||
83 | static inline struct cluster *cluster_find(u32 addr) | ||
84 | { | ||
85 | struct _zone *z_ptr = zone_find(addr); | ||
86 | |||
87 | if (z_ptr) | ||
88 | return z_ptr->clusters[1]; | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | #endif | ||
diff --git a/net/tipc/config.c b/net/tipc/config.c new file mode 100644 index 000000000000..8ddef4fce2c2 --- /dev/null +++ b/net/tipc/config.c | |||
@@ -0,0 +1,718 @@ | |||
1 | /* | ||
2 | * net/tipc/config.c: TIPC configuration management code | ||
3 | * | ||
4 | * Copyright (c) 2002-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "dbg.h" | ||
39 | #include "bearer.h" | ||
40 | #include "port.h" | ||
41 | #include "link.h" | ||
42 | #include "zone.h" | ||
43 | #include "addr.h" | ||
44 | #include "name_table.h" | ||
45 | #include "node.h" | ||
46 | #include "config.h" | ||
47 | #include "discover.h" | ||
48 | |||
49 | struct subscr_data { | ||
50 | char usr_handle[8]; | ||
51 | u32 domain; | ||
52 | u32 port_ref; | ||
53 | struct list_head subd_list; | ||
54 | }; | ||
55 | |||
56 | struct manager { | ||
57 | u32 user_ref; | ||
58 | u32 port_ref; | ||
59 | u32 subscr_ref; | ||
60 | u32 link_subscriptions; | ||
61 | struct list_head link_subscribers; | ||
62 | }; | ||
63 | |||
64 | static struct manager mng = { 0}; | ||
65 | |||
66 | static spinlock_t config_lock = SPIN_LOCK_UNLOCKED; | ||
67 | |||
68 | static const void *req_tlv_area; /* request message TLV area */ | ||
69 | static int req_tlv_space; /* request message TLV area size */ | ||
70 | static int rep_headroom; /* reply message headroom to use */ | ||
71 | |||
72 | |||
73 | void cfg_link_event(u32 addr, char *name, int up) | ||
74 | { | ||
75 | /* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */ | ||
76 | } | ||
77 | |||
78 | |||
79 | struct sk_buff *cfg_reply_alloc(int payload_size) | ||
80 | { | ||
81 | struct sk_buff *buf; | ||
82 | |||
83 | buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC); | ||
84 | if (buf) | ||
85 | skb_reserve(buf, rep_headroom); | ||
86 | return buf; | ||
87 | } | ||
88 | |||
89 | int cfg_append_tlv(struct sk_buff *buf, int tlv_type, | ||
90 | void *tlv_data, int tlv_data_size) | ||
91 | { | ||
92 | struct tlv_desc *tlv = (struct tlv_desc *)buf->tail; | ||
93 | int new_tlv_space = TLV_SPACE(tlv_data_size); | ||
94 | |||
95 | if (skb_tailroom(buf) < new_tlv_space) { | ||
96 | dbg("cfg_append_tlv unable to append TLV\n"); | ||
97 | return 0; | ||
98 | } | ||
99 | skb_put(buf, new_tlv_space); | ||
100 | tlv->tlv_type = htons(tlv_type); | ||
101 | tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size)); | ||
102 | if (tlv_data_size && tlv_data) | ||
103 | memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size); | ||
104 | return 1; | ||
105 | } | ||
106 | |||
107 | struct sk_buff *cfg_reply_unsigned_type(u16 tlv_type, u32 value) | ||
108 | { | ||
109 | struct sk_buff *buf; | ||
110 | u32 value_net; | ||
111 | |||
112 | buf = cfg_reply_alloc(TLV_SPACE(sizeof(value))); | ||
113 | if (buf) { | ||
114 | value_net = htonl(value); | ||
115 | cfg_append_tlv(buf, tlv_type, &value_net, | ||
116 | sizeof(value_net)); | ||
117 | } | ||
118 | return buf; | ||
119 | } | ||
120 | |||
121 | struct sk_buff *cfg_reply_string_type(u16 tlv_type, char *string) | ||
122 | { | ||
123 | struct sk_buff *buf; | ||
124 | int string_len = strlen(string) + 1; | ||
125 | |||
126 | buf = cfg_reply_alloc(TLV_SPACE(string_len)); | ||
127 | if (buf) | ||
128 | cfg_append_tlv(buf, tlv_type, string, string_len); | ||
129 | return buf; | ||
130 | } | ||
131 | |||
132 | |||
133 | |||
134 | |||
135 | #if 0 | ||
136 | |||
137 | /* Now obsolete code for handling commands not yet implemented the new way */ | ||
138 | |||
139 | int tipc_cfg_cmd(const struct tipc_cmd_msg * msg, | ||
140 | char *data, | ||
141 | u32 sz, | ||
142 | u32 *ret_size, | ||
143 | struct tipc_portid *orig) | ||
144 | { | ||
145 | int rv = -EINVAL; | ||
146 | u32 cmd = msg->cmd; | ||
147 | |||
148 | *ret_size = 0; | ||
149 | switch (cmd) { | ||
150 | case TIPC_REMOVE_LINK: | ||
151 | case TIPC_CMD_BLOCK_LINK: | ||
152 | case TIPC_CMD_UNBLOCK_LINK: | ||
153 | if (!cfg_check_connection(orig)) | ||
154 | rv = link_control(msg->argv.link_name, msg->cmd, 0); | ||
155 | break; | ||
156 | case TIPC_ESTABLISH: | ||
157 | { | ||
158 | int connected; | ||
159 | |||
160 | tipc_isconnected(mng.conn_port_ref, &connected); | ||
161 | if (connected || !orig) { | ||
162 | rv = TIPC_FAILURE; | ||
163 | break; | ||
164 | } | ||
165 | rv = tipc_connect2port(mng.conn_port_ref, orig); | ||
166 | if (rv == TIPC_OK) | ||
167 | orig = 0; | ||
168 | break; | ||
169 | } | ||
170 | case TIPC_GET_PEER_ADDRESS: | ||
171 | *ret_size = link_peer_addr(msg->argv.link_name, data, sz); | ||
172 | break; | ||
173 | case TIPC_GET_ROUTES: | ||
174 | rv = TIPC_OK; | ||
175 | break; | ||
176 | default: {} | ||
177 | } | ||
178 | if (*ret_size) | ||
179 | rv = TIPC_OK; | ||
180 | return rv; | ||
181 | } | ||
182 | |||
183 | static void cfg_cmd_event(struct tipc_cmd_msg *msg, | ||
184 | char *data, | ||
185 | u32 sz, | ||
186 | struct tipc_portid const *orig) | ||
187 | { | ||
188 | int rv = -EINVAL; | ||
189 | struct tipc_cmd_result_msg rmsg; | ||
190 | struct iovec msg_sect[2]; | ||
191 | int *arg; | ||
192 | |||
193 | msg->cmd = ntohl(msg->cmd); | ||
194 | |||
195 | cfg_prepare_res_msg(msg->cmd, msg->usr_handle, rv, &rmsg, msg_sect, | ||
196 | data, 0); | ||
197 | if (ntohl(msg->magic) != TIPC_MAGIC) | ||
198 | goto exit; | ||
199 | |||
200 | switch (msg->cmd) { | ||
201 | case TIPC_CREATE_LINK: | ||
202 | if (!cfg_check_connection(orig)) | ||
203 | rv = disc_create_link(&msg->argv.create_link); | ||
204 | break; | ||
205 | case TIPC_LINK_SUBSCRIBE: | ||
206 | { | ||
207 | struct subscr_data *sub; | ||
208 | |||
209 | if (mng.link_subscriptions > 64) | ||
210 | break; | ||
211 | sub = (struct subscr_data *)kmalloc(sizeof(*sub), | ||
212 | GFP_ATOMIC); | ||
213 | if (sub == NULL) { | ||
214 | warn("Memory squeeze; dropped remote link subscription\n"); | ||
215 | break; | ||
216 | } | ||
217 | INIT_LIST_HEAD(&sub->subd_list); | ||
218 | tipc_createport(mng.user_ref, | ||
219 | (void *)sub, | ||
220 | TIPC_HIGH_IMPORTANCE, | ||
221 | 0, | ||
222 | 0, | ||
223 | (tipc_conn_shutdown_event)cfg_linksubscr_cancel, | ||
224 | 0, | ||
225 | 0, | ||
226 | (tipc_conn_msg_event)cfg_linksubscr_cancel, | ||
227 | 0, | ||
228 | &sub->port_ref); | ||
229 | if (!sub->port_ref) { | ||
230 | kfree(sub); | ||
231 | break; | ||
232 | } | ||
233 | memcpy(sub->usr_handle,msg->usr_handle, | ||
234 | sizeof(sub->usr_handle)); | ||
235 | sub->domain = msg->argv.domain; | ||
236 | list_add_tail(&sub->subd_list, &mng.link_subscribers); | ||
237 | tipc_connect2port(sub->port_ref, orig); | ||
238 | rmsg.retval = TIPC_OK; | ||
239 | tipc_send(sub->port_ref, 2u, msg_sect); | ||
240 | mng.link_subscriptions++; | ||
241 | return; | ||
242 | } | ||
243 | default: | ||
244 | rv = tipc_cfg_cmd(msg, data, sz, (u32 *)&msg_sect[1].iov_len, orig); | ||
245 | } | ||
246 | exit: | ||
247 | rmsg.result_len = htonl(msg_sect[1].iov_len); | ||
248 | rmsg.retval = htonl(rv); | ||
249 | cfg_respond(msg_sect, 2u, orig); | ||
250 | } | ||
251 | #endif | ||
252 | |||
253 | static struct sk_buff *cfg_enable_bearer(void) | ||
254 | { | ||
255 | struct tipc_bearer_config *args; | ||
256 | |||
257 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG)) | ||
258 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
259 | |||
260 | args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area); | ||
261 | if (tipc_enable_bearer(args->name, | ||
262 | ntohl(args->detect_scope), | ||
263 | ntohl(args->priority))) | ||
264 | return cfg_reply_error_string("unable to enable bearer"); | ||
265 | |||
266 | return cfg_reply_none(); | ||
267 | } | ||
268 | |||
269 | static struct sk_buff *cfg_disable_bearer(void) | ||
270 | { | ||
271 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME)) | ||
272 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
273 | |||
274 | if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area))) | ||
275 | return cfg_reply_error_string("unable to disable bearer"); | ||
276 | |||
277 | return cfg_reply_none(); | ||
278 | } | ||
279 | |||
280 | static struct sk_buff *cfg_set_own_addr(void) | ||
281 | { | ||
282 | u32 addr; | ||
283 | |||
284 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) | ||
285 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
286 | |||
287 | addr = *(u32 *)TLV_DATA(req_tlv_area); | ||
288 | addr = ntohl(addr); | ||
289 | if (addr == tipc_own_addr) | ||
290 | return cfg_reply_none(); | ||
291 | if (!addr_node_valid(addr)) | ||
292 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
293 | " (node address)"); | ||
294 | if (tipc_own_addr) | ||
295 | return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
296 | " (cannot change node address once assigned)"); | ||
297 | |||
298 | spin_unlock_bh(&config_lock); | ||
299 | stop_net(); | ||
300 | tipc_own_addr = addr; | ||
301 | start_net(); | ||
302 | spin_lock_bh(&config_lock); | ||
303 | return cfg_reply_none(); | ||
304 | } | ||
305 | |||
306 | static struct sk_buff *cfg_set_remote_mng(void) | ||
307 | { | ||
308 | u32 value; | ||
309 | |||
310 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
311 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
312 | |||
313 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
314 | value = ntohl(value); | ||
315 | tipc_remote_management = (value != 0); | ||
316 | return cfg_reply_none(); | ||
317 | } | ||
318 | |||
319 | static struct sk_buff *cfg_set_max_publications(void) | ||
320 | { | ||
321 | u32 value; | ||
322 | |||
323 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
324 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
325 | |||
326 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
327 | value = ntohl(value); | ||
328 | if (value != delimit(value, 1, 65535)) | ||
329 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
330 | " (max publications must be 1-65535)"); | ||
331 | tipc_max_publications = value; | ||
332 | return cfg_reply_none(); | ||
333 | } | ||
334 | |||
335 | static struct sk_buff *cfg_set_max_subscriptions(void) | ||
336 | { | ||
337 | u32 value; | ||
338 | |||
339 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
340 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
341 | |||
342 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
343 | value = ntohl(value); | ||
344 | if (value != delimit(value, 1, 65535)) | ||
345 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
346 | " (max subscriptions must be 1-65535"); | ||
347 | tipc_max_subscriptions = value; | ||
348 | return cfg_reply_none(); | ||
349 | } | ||
350 | |||
351 | static struct sk_buff *cfg_set_max_ports(void) | ||
352 | { | ||
353 | int orig_mode; | ||
354 | u32 value; | ||
355 | |||
356 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
357 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
358 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
359 | value = ntohl(value); | ||
360 | if (value != delimit(value, 127, 65535)) | ||
361 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
362 | " (max ports must be 127-65535)"); | ||
363 | |||
364 | if (value == tipc_max_ports) | ||
365 | return cfg_reply_none(); | ||
366 | |||
367 | if (atomic_read(&tipc_user_count) > 2) | ||
368 | return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
369 | " (cannot change max ports while TIPC users exist)"); | ||
370 | |||
371 | spin_unlock_bh(&config_lock); | ||
372 | orig_mode = tipc_get_mode(); | ||
373 | if (orig_mode == TIPC_NET_MODE) | ||
374 | stop_net(); | ||
375 | stop_core(); | ||
376 | tipc_max_ports = value; | ||
377 | start_core(); | ||
378 | if (orig_mode == TIPC_NET_MODE) | ||
379 | start_net(); | ||
380 | spin_lock_bh(&config_lock); | ||
381 | return cfg_reply_none(); | ||
382 | } | ||
383 | |||
384 | static struct sk_buff *set_net_max(int value, int *parameter) | ||
385 | { | ||
386 | int orig_mode; | ||
387 | |||
388 | if (value != *parameter) { | ||
389 | orig_mode = tipc_get_mode(); | ||
390 | if (orig_mode == TIPC_NET_MODE) | ||
391 | stop_net(); | ||
392 | *parameter = value; | ||
393 | if (orig_mode == TIPC_NET_MODE) | ||
394 | start_net(); | ||
395 | } | ||
396 | |||
397 | return cfg_reply_none(); | ||
398 | } | ||
399 | |||
400 | static struct sk_buff *cfg_set_max_zones(void) | ||
401 | { | ||
402 | u32 value; | ||
403 | |||
404 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
405 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
406 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
407 | value = ntohl(value); | ||
408 | if (value != delimit(value, 1, 255)) | ||
409 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
410 | " (max zones must be 1-255)"); | ||
411 | return set_net_max(value, &tipc_max_zones); | ||
412 | } | ||
413 | |||
414 | static struct sk_buff *cfg_set_max_clusters(void) | ||
415 | { | ||
416 | u32 value; | ||
417 | |||
418 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
419 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
420 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
421 | value = ntohl(value); | ||
422 | if (value != 1) | ||
423 | return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
424 | " (max clusters fixed at 1)"); | ||
425 | return cfg_reply_none(); | ||
426 | } | ||
427 | |||
428 | static struct sk_buff *cfg_set_max_nodes(void) | ||
429 | { | ||
430 | u32 value; | ||
431 | |||
432 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
433 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
434 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
435 | value = ntohl(value); | ||
436 | if (value != delimit(value, 8, 2047)) | ||
437 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
438 | " (max nodes must be 8-2047)"); | ||
439 | return set_net_max(value, &tipc_max_nodes); | ||
440 | } | ||
441 | |||
442 | static struct sk_buff *cfg_set_max_slaves(void) | ||
443 | { | ||
444 | u32 value; | ||
445 | |||
446 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
447 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
448 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
449 | value = ntohl(value); | ||
450 | if (value != 0) | ||
451 | return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
452 | " (max secondary nodes fixed at 0)"); | ||
453 | return cfg_reply_none(); | ||
454 | } | ||
455 | |||
456 | static struct sk_buff *cfg_set_netid(void) | ||
457 | { | ||
458 | u32 value; | ||
459 | |||
460 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
461 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
462 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
463 | value = ntohl(value); | ||
464 | if (value != delimit(value, 1, 9999)) | ||
465 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
466 | " (network id must be 1-9999)"); | ||
467 | |||
468 | if (tipc_own_addr) | ||
469 | return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
470 | " (cannot change network id once part of network)"); | ||
471 | |||
472 | return set_net_max(value, &tipc_net_id); | ||
473 | } | ||
474 | |||
475 | struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, | ||
476 | int request_space, int reply_headroom) | ||
477 | { | ||
478 | struct sk_buff *rep_tlv_buf; | ||
479 | |||
480 | spin_lock_bh(&config_lock); | ||
481 | |||
482 | /* Save request and reply details in a well-known location */ | ||
483 | |||
484 | req_tlv_area = request_area; | ||
485 | req_tlv_space = request_space; | ||
486 | rep_headroom = reply_headroom; | ||
487 | |||
488 | /* Check command authorization */ | ||
489 | |||
490 | if (likely(orig_node == tipc_own_addr)) { | ||
491 | /* command is permitted */ | ||
492 | } else if (cmd >= 0x8000) { | ||
493 | rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
494 | " (cannot be done remotely)"); | ||
495 | goto exit; | ||
496 | } else if (!tipc_remote_management) { | ||
497 | rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NO_REMOTE); | ||
498 | goto exit; | ||
499 | } | ||
500 | else if (cmd >= 0x4000) { | ||
501 | u32 domain = 0; | ||
502 | |||
503 | if ((nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) || | ||
504 | (domain != orig_node)) { | ||
505 | rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR); | ||
506 | goto exit; | ||
507 | } | ||
508 | } | ||
509 | |||
510 | /* Call appropriate processing routine */ | ||
511 | |||
512 | switch (cmd) { | ||
513 | case TIPC_CMD_NOOP: | ||
514 | rep_tlv_buf = cfg_reply_none(); | ||
515 | break; | ||
516 | case TIPC_CMD_GET_NODES: | ||
517 | rep_tlv_buf = node_get_nodes(req_tlv_area, req_tlv_space); | ||
518 | break; | ||
519 | case TIPC_CMD_GET_LINKS: | ||
520 | rep_tlv_buf = node_get_links(req_tlv_area, req_tlv_space); | ||
521 | break; | ||
522 | case TIPC_CMD_SHOW_LINK_STATS: | ||
523 | rep_tlv_buf = link_cmd_show_stats(req_tlv_area, req_tlv_space); | ||
524 | break; | ||
525 | case TIPC_CMD_RESET_LINK_STATS: | ||
526 | rep_tlv_buf = link_cmd_reset_stats(req_tlv_area, req_tlv_space); | ||
527 | break; | ||
528 | case TIPC_CMD_SHOW_NAME_TABLE: | ||
529 | rep_tlv_buf = nametbl_get(req_tlv_area, req_tlv_space); | ||
530 | break; | ||
531 | case TIPC_CMD_GET_BEARER_NAMES: | ||
532 | rep_tlv_buf = bearer_get_names(); | ||
533 | break; | ||
534 | case TIPC_CMD_GET_MEDIA_NAMES: | ||
535 | rep_tlv_buf = media_get_names(); | ||
536 | break; | ||
537 | case TIPC_CMD_SHOW_PORTS: | ||
538 | rep_tlv_buf = port_get_ports(); | ||
539 | break; | ||
540 | #if 0 | ||
541 | case TIPC_CMD_SHOW_PORT_STATS: | ||
542 | rep_tlv_buf = port_show_stats(req_tlv_area, req_tlv_space); | ||
543 | break; | ||
544 | case TIPC_CMD_RESET_PORT_STATS: | ||
545 | rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED); | ||
546 | break; | ||
547 | #endif | ||
548 | case TIPC_CMD_SET_LOG_SIZE: | ||
549 | rep_tlv_buf = log_resize(req_tlv_area, req_tlv_space); | ||
550 | break; | ||
551 | case TIPC_CMD_DUMP_LOG: | ||
552 | rep_tlv_buf = log_dump(); | ||
553 | break; | ||
554 | case TIPC_CMD_SET_LINK_TOL: | ||
555 | case TIPC_CMD_SET_LINK_PRI: | ||
556 | case TIPC_CMD_SET_LINK_WINDOW: | ||
557 | rep_tlv_buf = link_cmd_config(req_tlv_area, req_tlv_space, cmd); | ||
558 | break; | ||
559 | case TIPC_CMD_ENABLE_BEARER: | ||
560 | rep_tlv_buf = cfg_enable_bearer(); | ||
561 | break; | ||
562 | case TIPC_CMD_DISABLE_BEARER: | ||
563 | rep_tlv_buf = cfg_disable_bearer(); | ||
564 | break; | ||
565 | case TIPC_CMD_SET_NODE_ADDR: | ||
566 | rep_tlv_buf = cfg_set_own_addr(); | ||
567 | break; | ||
568 | case TIPC_CMD_SET_REMOTE_MNG: | ||
569 | rep_tlv_buf = cfg_set_remote_mng(); | ||
570 | break; | ||
571 | case TIPC_CMD_SET_MAX_PORTS: | ||
572 | rep_tlv_buf = cfg_set_max_ports(); | ||
573 | break; | ||
574 | case TIPC_CMD_SET_MAX_PUBL: | ||
575 | rep_tlv_buf = cfg_set_max_publications(); | ||
576 | break; | ||
577 | case TIPC_CMD_SET_MAX_SUBSCR: | ||
578 | rep_tlv_buf = cfg_set_max_subscriptions(); | ||
579 | break; | ||
580 | case TIPC_CMD_SET_MAX_ZONES: | ||
581 | rep_tlv_buf = cfg_set_max_zones(); | ||
582 | break; | ||
583 | case TIPC_CMD_SET_MAX_CLUSTERS: | ||
584 | rep_tlv_buf = cfg_set_max_clusters(); | ||
585 | break; | ||
586 | case TIPC_CMD_SET_MAX_NODES: | ||
587 | rep_tlv_buf = cfg_set_max_nodes(); | ||
588 | break; | ||
589 | case TIPC_CMD_SET_MAX_SLAVES: | ||
590 | rep_tlv_buf = cfg_set_max_slaves(); | ||
591 | break; | ||
592 | case TIPC_CMD_SET_NETID: | ||
593 | rep_tlv_buf = cfg_set_netid(); | ||
594 | break; | ||
595 | case TIPC_CMD_GET_REMOTE_MNG: | ||
596 | rep_tlv_buf = cfg_reply_unsigned(tipc_remote_management); | ||
597 | break; | ||
598 | case TIPC_CMD_GET_MAX_PORTS: | ||
599 | rep_tlv_buf = cfg_reply_unsigned(tipc_max_ports); | ||
600 | break; | ||
601 | case TIPC_CMD_GET_MAX_PUBL: | ||
602 | rep_tlv_buf = cfg_reply_unsigned(tipc_max_publications); | ||
603 | break; | ||
604 | case TIPC_CMD_GET_MAX_SUBSCR: | ||
605 | rep_tlv_buf = cfg_reply_unsigned(tipc_max_subscriptions); | ||
606 | break; | ||
607 | case TIPC_CMD_GET_MAX_ZONES: | ||
608 | rep_tlv_buf = cfg_reply_unsigned(tipc_max_zones); | ||
609 | break; | ||
610 | case TIPC_CMD_GET_MAX_CLUSTERS: | ||
611 | rep_tlv_buf = cfg_reply_unsigned(tipc_max_clusters); | ||
612 | break; | ||
613 | case TIPC_CMD_GET_MAX_NODES: | ||
614 | rep_tlv_buf = cfg_reply_unsigned(tipc_max_nodes); | ||
615 | break; | ||
616 | case TIPC_CMD_GET_MAX_SLAVES: | ||
617 | rep_tlv_buf = cfg_reply_unsigned(tipc_max_slaves); | ||
618 | break; | ||
619 | case TIPC_CMD_GET_NETID: | ||
620 | rep_tlv_buf = cfg_reply_unsigned(tipc_net_id); | ||
621 | break; | ||
622 | default: | ||
623 | rep_tlv_buf = NULL; | ||
624 | break; | ||
625 | } | ||
626 | |||
627 | /* Return reply buffer */ | ||
628 | exit: | ||
629 | spin_unlock_bh(&config_lock); | ||
630 | return rep_tlv_buf; | ||
631 | } | ||
632 | |||
633 | static void cfg_named_msg_event(void *userdata, | ||
634 | u32 port_ref, | ||
635 | struct sk_buff **buf, | ||
636 | const unchar *msg, | ||
637 | u32 size, | ||
638 | u32 importance, | ||
639 | struct tipc_portid const *orig, | ||
640 | struct tipc_name_seq const *dest) | ||
641 | { | ||
642 | struct tipc_cfg_msg_hdr *req_hdr; | ||
643 | struct tipc_cfg_msg_hdr *rep_hdr; | ||
644 | struct sk_buff *rep_buf; | ||
645 | |||
646 | /* Validate configuration message header (ignore invalid message) */ | ||
647 | |||
648 | req_hdr = (struct tipc_cfg_msg_hdr *)msg; | ||
649 | if ((size < sizeof(*req_hdr)) || | ||
650 | (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || | ||
651 | (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) { | ||
652 | warn("discarded invalid configuration message\n"); | ||
653 | return; | ||
654 | } | ||
655 | |||
656 | /* Generate reply for request (if can't, return request) */ | ||
657 | |||
658 | rep_buf = cfg_do_cmd(orig->node, | ||
659 | ntohs(req_hdr->tcm_type), | ||
660 | msg + sizeof(*req_hdr), | ||
661 | size - sizeof(*req_hdr), | ||
662 | BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr)); | ||
663 | if (rep_buf) { | ||
664 | skb_push(rep_buf, sizeof(*rep_hdr)); | ||
665 | rep_hdr = (struct tipc_cfg_msg_hdr *)rep_buf->data; | ||
666 | memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); | ||
667 | rep_hdr->tcm_len = htonl(rep_buf->len); | ||
668 | rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); | ||
669 | } else { | ||
670 | rep_buf = *buf; | ||
671 | *buf = NULL; | ||
672 | } | ||
673 | |||
674 | /* NEED TO ADD CODE TO HANDLE FAILED SEND (SUCH AS CONGESTION) */ | ||
675 | tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len); | ||
676 | } | ||
677 | |||
678 | int cfg_init(void) | ||
679 | { | ||
680 | struct tipc_name_seq seq; | ||
681 | int res; | ||
682 | |||
683 | memset(&mng, 0, sizeof(mng)); | ||
684 | INIT_LIST_HEAD(&mng.link_subscribers); | ||
685 | |||
686 | res = tipc_attach(&mng.user_ref, 0, 0); | ||
687 | if (res) | ||
688 | goto failed; | ||
689 | |||
690 | res = tipc_createport(mng.user_ref, 0, TIPC_CRITICAL_IMPORTANCE, | ||
691 | NULL, NULL, NULL, | ||
692 | NULL, cfg_named_msg_event, NULL, | ||
693 | NULL, &mng.port_ref); | ||
694 | if (res) | ||
695 | goto failed; | ||
696 | |||
697 | seq.type = TIPC_CFG_SRV; | ||
698 | seq.lower = seq.upper = tipc_own_addr; | ||
699 | res = nametbl_publish_rsv(mng.port_ref, TIPC_ZONE_SCOPE, &seq); | ||
700 | if (res) | ||
701 | goto failed; | ||
702 | |||
703 | return 0; | ||
704 | |||
705 | failed: | ||
706 | err("Unable to create configuration service\n"); | ||
707 | tipc_detach(mng.user_ref); | ||
708 | mng.user_ref = 0; | ||
709 | return res; | ||
710 | } | ||
711 | |||
712 | void cfg_stop(void) | ||
713 | { | ||
714 | if (mng.user_ref) { | ||
715 | tipc_detach(mng.user_ref); | ||
716 | mng.user_ref = 0; | ||
717 | } | ||
718 | } | ||
diff --git a/net/tipc/config.h b/net/tipc/config.h new file mode 100644 index 000000000000..646377d40454 --- /dev/null +++ b/net/tipc/config.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * net/tipc/config.h: Include file for TIPC configuration service code | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_CONFIG_H | ||
38 | #define _TIPC_CONFIG_H | ||
39 | |||
40 | /* ---------------------------------------------------------------------- */ | ||
41 | |||
42 | #include <linux/tipc.h> | ||
43 | #include <linux/tipc_config.h> | ||
44 | #include "link.h" | ||
45 | |||
46 | struct sk_buff *cfg_reply_alloc(int payload_size); | ||
47 | int cfg_append_tlv(struct sk_buff *buf, int tlv_type, | ||
48 | void *tlv_data, int tlv_data_size); | ||
49 | struct sk_buff *cfg_reply_unsigned_type(u16 tlv_type, u32 value); | ||
50 | struct sk_buff *cfg_reply_string_type(u16 tlv_type, char *string); | ||
51 | |||
52 | static inline struct sk_buff *cfg_reply_none(void) | ||
53 | { | ||
54 | return cfg_reply_alloc(0); | ||
55 | } | ||
56 | |||
57 | static inline struct sk_buff *cfg_reply_unsigned(u32 value) | ||
58 | { | ||
59 | return cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value); | ||
60 | } | ||
61 | |||
62 | static inline struct sk_buff *cfg_reply_error_string(char *string) | ||
63 | { | ||
64 | return cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string); | ||
65 | } | ||
66 | |||
67 | static inline struct sk_buff *cfg_reply_ultra_string(char *string) | ||
68 | { | ||
69 | return cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string); | ||
70 | } | ||
71 | |||
72 | struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd, | ||
73 | const void *req_tlv_area, int req_tlv_space, | ||
74 | int headroom); | ||
75 | |||
76 | void cfg_link_event(u32 addr, char *name, int up); | ||
77 | int cfg_init(void); | ||
78 | void cfg_stop(void); | ||
79 | |||
80 | #endif | ||
diff --git a/net/tipc/core.c b/net/tipc/core.c new file mode 100644 index 000000000000..e83ac06e31ba --- /dev/null +++ b/net/tipc/core.c | |||
@@ -0,0 +1,285 @@ | |||
1 | /* | ||
2 | * net/tipc/core.c: TIPC module code | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include <linux/init.h> | ||
38 | #include <linux/module.h> | ||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/version.h> | ||
41 | #include <linux/random.h> | ||
42 | |||
43 | #include "core.h" | ||
44 | #include "dbg.h" | ||
45 | #include "ref.h" | ||
46 | #include "net.h" | ||
47 | #include "user_reg.h" | ||
48 | #include "name_table.h" | ||
49 | #include "subscr.h" | ||
50 | #include "config.h" | ||
51 | |||
52 | int eth_media_start(void); | ||
53 | void eth_media_stop(void); | ||
54 | int handler_start(void); | ||
55 | void handler_stop(void); | ||
56 | int socket_init(void); | ||
57 | void socket_stop(void); | ||
58 | int netlink_start(void); | ||
59 | void netlink_stop(void); | ||
60 | |||
61 | #define MOD_NAME "tipc_start: " | ||
62 | |||
63 | #ifndef CONFIG_TIPC_ZONES | ||
64 | #define CONFIG_TIPC_ZONES 3 | ||
65 | #endif | ||
66 | |||
67 | #ifndef CONFIG_TIPC_CLUSTERS | ||
68 | #define CONFIG_TIPC_CLUSTERS 1 | ||
69 | #endif | ||
70 | |||
71 | #ifndef CONFIG_TIPC_NODES | ||
72 | #define CONFIG_TIPC_NODES 255 | ||
73 | #endif | ||
74 | |||
75 | #ifndef CONFIG_TIPC_SLAVE_NODES | ||
76 | #define CONFIG_TIPC_SLAVE_NODES 0 | ||
77 | #endif | ||
78 | |||
79 | #ifndef CONFIG_TIPC_PORTS | ||
80 | #define CONFIG_TIPC_PORTS 8191 | ||
81 | #endif | ||
82 | |||
83 | #ifndef CONFIG_TIPC_LOG | ||
84 | #define CONFIG_TIPC_LOG 0 | ||
85 | #endif | ||
86 | |||
87 | /* global variables used by multiple sub-systems within TIPC */ | ||
88 | |||
89 | int tipc_mode = TIPC_NOT_RUNNING; | ||
90 | int tipc_random; | ||
91 | atomic_t tipc_user_count = ATOMIC_INIT(0); | ||
92 | |||
93 | const char tipc_alphabet[] = | ||
94 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; | ||
95 | |||
96 | /* configurable TIPC parameters */ | ||
97 | |||
98 | u32 tipc_own_addr; | ||
99 | int tipc_max_zones; | ||
100 | int tipc_max_clusters; | ||
101 | int tipc_max_nodes; | ||
102 | int tipc_max_slaves; | ||
103 | int tipc_max_ports; | ||
104 | int tipc_max_subscriptions; | ||
105 | int tipc_max_publications; | ||
106 | int tipc_net_id; | ||
107 | int tipc_remote_management; | ||
108 | |||
109 | |||
110 | int tipc_get_mode(void) | ||
111 | { | ||
112 | return tipc_mode; | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * stop_net - shut down TIPC networking sub-systems | ||
117 | */ | ||
118 | |||
119 | void stop_net(void) | ||
120 | { | ||
121 | eth_media_stop(); | ||
122 | tipc_stop_net(); | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * start_net - start TIPC networking sub-systems | ||
127 | */ | ||
128 | |||
129 | int start_net(void) | ||
130 | { | ||
131 | int res; | ||
132 | |||
133 | if ((res = tipc_start_net()) || | ||
134 | (res = eth_media_start())) { | ||
135 | stop_net(); | ||
136 | } | ||
137 | return res; | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * stop_core - switch TIPC from SINGLE NODE to NOT RUNNING mode | ||
142 | */ | ||
143 | |||
144 | void stop_core(void) | ||
145 | { | ||
146 | if (tipc_mode != TIPC_NODE_MODE) | ||
147 | return; | ||
148 | |||
149 | tipc_mode = TIPC_NOT_RUNNING; | ||
150 | |||
151 | netlink_stop(); | ||
152 | handler_stop(); | ||
153 | cfg_stop(); | ||
154 | subscr_stop(); | ||
155 | reg_stop(); | ||
156 | nametbl_stop(); | ||
157 | ref_table_stop(); | ||
158 | socket_stop(); | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * start_core - switch TIPC from NOT RUNNING to SINGLE NODE mode | ||
163 | */ | ||
164 | |||
165 | int start_core(void) | ||
166 | { | ||
167 | int res; | ||
168 | |||
169 | if (tipc_mode != TIPC_NOT_RUNNING) | ||
170 | return -ENOPROTOOPT; | ||
171 | |||
172 | get_random_bytes(&tipc_random, sizeof(tipc_random)); | ||
173 | tipc_mode = TIPC_NODE_MODE; | ||
174 | |||
175 | if ((res = handler_start()) || | ||
176 | (res = ref_table_init(tipc_max_ports + tipc_max_subscriptions, | ||
177 | tipc_random)) || | ||
178 | (res = reg_start()) || | ||
179 | (res = nametbl_init()) || | ||
180 | (res = k_signal((Handler)subscr_start, 0)) || | ||
181 | (res = k_signal((Handler)cfg_init, 0)) || | ||
182 | (res = netlink_start()) || | ||
183 | (res = socket_init())) { | ||
184 | stop_core(); | ||
185 | } | ||
186 | return res; | ||
187 | } | ||
188 | |||
189 | |||
190 | static int __init tipc_init(void) | ||
191 | { | ||
192 | int res; | ||
193 | |||
194 | log_reinit(CONFIG_TIPC_LOG); | ||
195 | info("Activated (compiled " __DATE__ " " __TIME__ ")\n"); | ||
196 | |||
197 | tipc_own_addr = 0; | ||
198 | tipc_remote_management = 1; | ||
199 | tipc_max_publications = 10000; | ||
200 | tipc_max_subscriptions = 2000; | ||
201 | tipc_max_ports = delimit(CONFIG_TIPC_PORTS, 127, 65536); | ||
202 | tipc_max_zones = delimit(CONFIG_TIPC_ZONES, 1, 511); | ||
203 | tipc_max_clusters = delimit(CONFIG_TIPC_CLUSTERS, 1, 1); | ||
204 | tipc_max_nodes = delimit(CONFIG_TIPC_NODES, 8, 2047); | ||
205 | tipc_max_slaves = delimit(CONFIG_TIPC_SLAVE_NODES, 0, 2047); | ||
206 | tipc_net_id = 4711; | ||
207 | |||
208 | if ((res = start_core())) | ||
209 | err("Unable to start in single node mode\n"); | ||
210 | else | ||
211 | info("Started in single node mode\n"); | ||
212 | return res; | ||
213 | } | ||
214 | |||
215 | static void __exit tipc_exit(void) | ||
216 | { | ||
217 | stop_net(); | ||
218 | stop_core(); | ||
219 | info("Deactivated\n"); | ||
220 | log_stop(); | ||
221 | } | ||
222 | |||
223 | module_init(tipc_init); | ||
224 | module_exit(tipc_exit); | ||
225 | |||
226 | MODULE_DESCRIPTION("TIPC: Transparent Inter Process Communication"); | ||
227 | MODULE_LICENSE("Dual BSD/GPL"); | ||
228 | |||
229 | /* Native TIPC API for kernel-space applications (see tipc.h) */ | ||
230 | |||
231 | EXPORT_SYMBOL(tipc_attach); | ||
232 | EXPORT_SYMBOL(tipc_detach); | ||
233 | EXPORT_SYMBOL(tipc_get_addr); | ||
234 | EXPORT_SYMBOL(tipc_get_mode); | ||
235 | EXPORT_SYMBOL(tipc_createport); | ||
236 | EXPORT_SYMBOL(tipc_deleteport); | ||
237 | EXPORT_SYMBOL(tipc_ownidentity); | ||
238 | EXPORT_SYMBOL(tipc_portimportance); | ||
239 | EXPORT_SYMBOL(tipc_set_portimportance); | ||
240 | EXPORT_SYMBOL(tipc_portunreliable); | ||
241 | EXPORT_SYMBOL(tipc_set_portunreliable); | ||
242 | EXPORT_SYMBOL(tipc_portunreturnable); | ||
243 | EXPORT_SYMBOL(tipc_set_portunreturnable); | ||
244 | EXPORT_SYMBOL(tipc_publish); | ||
245 | EXPORT_SYMBOL(tipc_withdraw); | ||
246 | EXPORT_SYMBOL(tipc_connect2port); | ||
247 | EXPORT_SYMBOL(tipc_disconnect); | ||
248 | EXPORT_SYMBOL(tipc_shutdown); | ||
249 | EXPORT_SYMBOL(tipc_isconnected); | ||
250 | EXPORT_SYMBOL(tipc_peer); | ||
251 | EXPORT_SYMBOL(tipc_ref_valid); | ||
252 | EXPORT_SYMBOL(tipc_send); | ||
253 | EXPORT_SYMBOL(tipc_send_buf); | ||
254 | EXPORT_SYMBOL(tipc_send2name); | ||
255 | EXPORT_SYMBOL(tipc_forward2name); | ||
256 | EXPORT_SYMBOL(tipc_send_buf2name); | ||
257 | EXPORT_SYMBOL(tipc_forward_buf2name); | ||
258 | EXPORT_SYMBOL(tipc_send2port); | ||
259 | EXPORT_SYMBOL(tipc_forward2port); | ||
260 | EXPORT_SYMBOL(tipc_send_buf2port); | ||
261 | EXPORT_SYMBOL(tipc_forward_buf2port); | ||
262 | EXPORT_SYMBOL(tipc_multicast); | ||
263 | /* EXPORT_SYMBOL(tipc_multicast_buf); not available yet */ | ||
264 | EXPORT_SYMBOL(tipc_ispublished); | ||
265 | EXPORT_SYMBOL(tipc_available_nodes); | ||
266 | |||
267 | /* TIPC API for external bearers (see tipc_bearer.h) */ | ||
268 | |||
269 | EXPORT_SYMBOL(tipc_block_bearer); | ||
270 | EXPORT_SYMBOL(tipc_continue); | ||
271 | EXPORT_SYMBOL(tipc_disable_bearer); | ||
272 | EXPORT_SYMBOL(tipc_enable_bearer); | ||
273 | EXPORT_SYMBOL(tipc_recv_msg); | ||
274 | EXPORT_SYMBOL(tipc_register_media); | ||
275 | |||
276 | /* TIPC API for external APIs (see tipc_port.h) */ | ||
277 | |||
278 | EXPORT_SYMBOL(tipc_createport_raw); | ||
279 | EXPORT_SYMBOL(tipc_set_msg_option); | ||
280 | EXPORT_SYMBOL(tipc_reject_msg); | ||
281 | EXPORT_SYMBOL(tipc_send_buf_fast); | ||
282 | EXPORT_SYMBOL(tipc_acknowledge); | ||
283 | EXPORT_SYMBOL(tipc_get_port); | ||
284 | EXPORT_SYMBOL(tipc_get_handle); | ||
285 | |||
diff --git a/net/tipc/core.h b/net/tipc/core.h new file mode 100644 index 000000000000..b69b60b2cc86 --- /dev/null +++ b/net/tipc/core.h | |||
@@ -0,0 +1,316 @@ | |||
1 | /* | ||
2 | * net/tipc/core.h: Include file for TIPC global declarations | ||
3 | * | ||
4 | * Copyright (c) 2005-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_CORE_H | ||
38 | #define _TIPC_CORE_H | ||
39 | |||
40 | #include <net/tipc/tipc.h> | ||
41 | #include <linux/types.h> | ||
42 | #include <linux/kernel.h> | ||
43 | #include <linux/errno.h> | ||
44 | #include <linux/mm.h> | ||
45 | #include <linux/timer.h> | ||
46 | #include <linux/string.h> | ||
47 | #include <asm/uaccess.h> | ||
48 | #include <linux/interrupt.h> | ||
49 | #include <asm/atomic.h> | ||
50 | #include <asm/hardirq.h> | ||
51 | #include <linux/netdevice.h> | ||
52 | #include <linux/in.h> | ||
53 | #include <linux/list.h> | ||
54 | #include <linux/vmalloc.h> | ||
55 | |||
56 | /* | ||
57 | * TIPC debugging code | ||
58 | */ | ||
59 | |||
60 | #define assert(i) BUG_ON(!(i)) | ||
61 | |||
62 | struct tipc_msg; | ||
63 | extern struct print_buf *CONS, *LOG; | ||
64 | extern struct print_buf *TEE(struct print_buf *, struct print_buf *); | ||
65 | void msg_print(struct print_buf*,struct tipc_msg *,const char*); | ||
66 | void tipc_printf(struct print_buf *, const char *fmt, ...); | ||
67 | void tipc_dump(struct print_buf*,const char *fmt, ...); | ||
68 | |||
69 | #ifdef CONFIG_TIPC_DEBUG | ||
70 | |||
71 | /* | ||
72 | * TIPC debug support included: | ||
73 | * - system messages are printed to TIPC_OUTPUT print buffer | ||
74 | * - debug messages are printed to DBG_OUTPUT print buffer | ||
75 | */ | ||
76 | |||
77 | #define err(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_ERR "TIPC: " fmt, ## arg) | ||
78 | #define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg) | ||
79 | #define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg) | ||
80 | |||
81 | #define dbg(fmt, arg...) do {if (DBG_OUTPUT) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0) | ||
82 | #define msg_dbg(msg, txt) do {if (DBG_OUTPUT) msg_print(DBG_OUTPUT, msg, txt);} while(0) | ||
83 | #define dump(fmt, arg...) do {if (DBG_OUTPUT) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0) | ||
84 | |||
85 | |||
86 | /* | ||
87 | * By default, TIPC_OUTPUT is defined to be system console and TIPC log buffer, | ||
88 | * while DBG_OUTPUT is the null print buffer. These defaults can be changed | ||
89 | * here, or on a per .c file basis, by redefining these symbols. The following | ||
90 | * print buffer options are available: | ||
91 | * | ||
92 | * NULL : Output to null print buffer (i.e. print nowhere) | ||
93 | * CONS : Output to system console | ||
94 | * LOG : Output to TIPC log buffer | ||
95 | * &buf : Output to user-defined buffer (struct print_buf *) | ||
96 | * TEE(&buf_a,&buf_b) : Output to two print buffers (eg. TEE(CONS,LOG) ) | ||
97 | */ | ||
98 | |||
99 | #ifndef TIPC_OUTPUT | ||
100 | #define TIPC_OUTPUT TEE(CONS,LOG) | ||
101 | #endif | ||
102 | |||
103 | #ifndef DBG_OUTPUT | ||
104 | #define DBG_OUTPUT NULL | ||
105 | #endif | ||
106 | |||
107 | #else | ||
108 | |||
109 | #ifndef DBG_OUTPUT | ||
110 | #define DBG_OUTPUT NULL | ||
111 | #endif | ||
112 | |||
113 | /* | ||
114 | * TIPC debug support not included: | ||
115 | * - system messages are printed to system console | ||
116 | * - debug messages are not printed | ||
117 | */ | ||
118 | |||
119 | #define err(fmt, arg...) printk(KERN_ERR "TIPC: " fmt , ## arg) | ||
120 | #define info(fmt, arg...) printk(KERN_INFO "TIPC: " fmt , ## arg) | ||
121 | #define warn(fmt, arg...) printk(KERN_WARNING "TIPC: " fmt , ## arg) | ||
122 | |||
123 | #define dbg(fmt, arg...) do {} while (0) | ||
124 | #define msg_dbg(msg,txt) do {} while (0) | ||
125 | #define dump(fmt,arg...) do {} while (0) | ||
126 | |||
127 | #endif | ||
128 | |||
129 | |||
130 | /* | ||
131 | * TIPC-specific error codes | ||
132 | */ | ||
133 | |||
134 | #define ELINKCONG EAGAIN /* link congestion <=> resource unavailable */ | ||
135 | |||
136 | /* | ||
137 | * Global configuration variables | ||
138 | */ | ||
139 | |||
140 | extern u32 tipc_own_addr; | ||
141 | extern int tipc_max_zones; | ||
142 | extern int tipc_max_clusters; | ||
143 | extern int tipc_max_nodes; | ||
144 | extern int tipc_max_slaves; | ||
145 | extern int tipc_max_ports; | ||
146 | extern int tipc_max_subscriptions; | ||
147 | extern int tipc_max_publications; | ||
148 | extern int tipc_net_id; | ||
149 | extern int tipc_remote_management; | ||
150 | |||
151 | /* | ||
152 | * Other global variables | ||
153 | */ | ||
154 | |||
155 | extern int tipc_mode; | ||
156 | extern int tipc_random; | ||
157 | extern const char tipc_alphabet[]; | ||
158 | extern atomic_t tipc_user_count; | ||
159 | |||
160 | |||
161 | /* | ||
162 | * Routines available to privileged subsystems | ||
163 | */ | ||
164 | |||
165 | extern int start_core(void); | ||
166 | extern void stop_core(void); | ||
167 | extern int start_net(void); | ||
168 | extern void stop_net(void); | ||
169 | |||
170 | static inline int delimit(int val, int min, int max) | ||
171 | { | ||
172 | if (val > max) | ||
173 | return max; | ||
174 | if (val < min) | ||
175 | return min; | ||
176 | return val; | ||
177 | } | ||
178 | |||
179 | |||
180 | /* | ||
181 | * TIPC timer and signal code | ||
182 | */ | ||
183 | |||
184 | typedef void (*Handler) (unsigned long); | ||
185 | |||
186 | u32 k_signal(Handler routine, unsigned long argument); | ||
187 | |||
188 | /** | ||
189 | * k_init_timer - initialize a timer | ||
190 | * @timer: pointer to timer structure | ||
191 | * @routine: pointer to routine to invoke when timer expires | ||
192 | * @argument: value to pass to routine when timer expires | ||
193 | * | ||
194 | * Timer must be initialized before use (and terminated when no longer needed). | ||
195 | */ | ||
196 | |||
197 | static inline void k_init_timer(struct timer_list *timer, Handler routine, | ||
198 | unsigned long argument) | ||
199 | { | ||
200 | dbg("initializing timer %p\n", timer); | ||
201 | init_timer(timer); | ||
202 | timer->function = routine; | ||
203 | timer->data = argument; | ||
204 | } | ||
205 | |||
206 | /** | ||
207 | * k_start_timer - start a timer | ||
208 | * @timer: pointer to timer structure | ||
209 | * @msec: time to delay (in ms) | ||
210 | * | ||
211 | * Schedules a previously initialized timer for later execution. | ||
212 | * If timer is already running, the new timeout overrides the previous request. | ||
213 | * | ||
214 | * To ensure the timer doesn't expire before the specified delay elapses, | ||
215 | * the amount of delay is rounded up when converting to the jiffies | ||
216 | * then an additional jiffy is added to account for the fact that | ||
217 | * the starting time may be in the middle of the current jiffy. | ||
218 | */ | ||
219 | |||
220 | static inline void k_start_timer(struct timer_list *timer, unsigned long msec) | ||
221 | { | ||
222 | dbg("starting timer %p for %u\n", timer, msec); | ||
223 | mod_timer(timer, jiffies + msecs_to_jiffies(msec) + 1); | ||
224 | } | ||
225 | |||
226 | /** | ||
227 | * k_cancel_timer - cancel a timer | ||
228 | * @timer: pointer to timer structure | ||
229 | * | ||
230 | * Cancels a previously initialized timer. | ||
231 | * Can be called safely even if the timer is already inactive. | ||
232 | * | ||
233 | * WARNING: Must not be called when holding locks required by the timer's | ||
234 | * timeout routine, otherwise deadlock can occur on SMP systems! | ||
235 | */ | ||
236 | |||
237 | static inline void k_cancel_timer(struct timer_list *timer) | ||
238 | { | ||
239 | dbg("cancelling timer %p\n", timer); | ||
240 | del_timer_sync(timer); | ||
241 | } | ||
242 | |||
243 | /** | ||
244 | * k_term_timer - terminate a timer | ||
245 | * @timer: pointer to timer structure | ||
246 | * | ||
247 | * Prevents further use of a previously initialized timer. | ||
248 | * | ||
249 | * WARNING: Caller must ensure timer isn't currently running. | ||
250 | * | ||
251 | * (Do not "enhance" this routine to automatically cancel an active timer, | ||
252 | * otherwise deadlock can arise when a timeout routine calls k_term_timer.) | ||
253 | */ | ||
254 | |||
255 | static inline void k_term_timer(struct timer_list *timer) | ||
256 | { | ||
257 | dbg("terminating timer %p\n", timer); | ||
258 | } | ||
259 | |||
260 | |||
261 | /* | ||
262 | * TIPC message buffer code | ||
263 | * | ||
264 | * TIPC message buffer headroom leaves room for 14 byte Ethernet header, | ||
265 | * while ensuring TIPC header is word aligned for quicker access | ||
266 | */ | ||
267 | |||
268 | #define BUF_HEADROOM 16u | ||
269 | |||
270 | struct tipc_skb_cb { | ||
271 | void *handle; | ||
272 | }; | ||
273 | |||
274 | #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) | ||
275 | |||
276 | |||
277 | static inline struct tipc_msg *buf_msg(struct sk_buff *skb) | ||
278 | { | ||
279 | return (struct tipc_msg *)skb->data; | ||
280 | } | ||
281 | |||
282 | /** | ||
283 | * buf_acquire - creates a TIPC message buffer | ||
284 | * @size: message size (including TIPC header) | ||
285 | * | ||
286 | * Returns a new buffer. Space is reserved for a data link header. | ||
287 | */ | ||
288 | |||
289 | static inline struct sk_buff *buf_acquire(u32 size) | ||
290 | { | ||
291 | struct sk_buff *skb; | ||
292 | unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u; | ||
293 | |||
294 | skb = alloc_skb(buf_size, GFP_ATOMIC); | ||
295 | if (skb) { | ||
296 | skb_reserve(skb, BUF_HEADROOM); | ||
297 | skb_put(skb, size); | ||
298 | skb->next = NULL; | ||
299 | } | ||
300 | return skb; | ||
301 | } | ||
302 | |||
303 | /** | ||
304 | * buf_discard - frees a TIPC message buffer | ||
305 | * @skb: message buffer | ||
306 | * | ||
307 | * Frees a new buffer. If passed NULL, just returns. | ||
308 | */ | ||
309 | |||
310 | static inline void buf_discard(struct sk_buff *skb) | ||
311 | { | ||
312 | if (likely(skb != NULL)) | ||
313 | kfree_skb(skb); | ||
314 | } | ||
315 | |||
316 | #endif | ||
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c new file mode 100644 index 000000000000..7ed60a1cfbb8 --- /dev/null +++ b/net/tipc/dbg.c | |||
@@ -0,0 +1,395 @@ | |||
1 | /* | ||
2 | * net/tipc/dbg.c: TIPC print buffer routines for debuggign | ||
3 | * | ||
4 | * Copyright (c) 1996-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "config.h" | ||
39 | #include "dbg.h" | ||
40 | |||
41 | #define MAX_STRING 512 | ||
42 | |||
43 | static char print_string[MAX_STRING]; | ||
44 | static spinlock_t print_lock = SPIN_LOCK_UNLOCKED; | ||
45 | |||
46 | static struct print_buf cons_buf = { NULL, 0, NULL, NULL }; | ||
47 | struct print_buf *CONS = &cons_buf; | ||
48 | |||
49 | static struct print_buf log_buf = { NULL, 0, NULL, NULL }; | ||
50 | struct print_buf *LOG = &log_buf; | ||
51 | |||
52 | |||
53 | #define FORMAT(PTR,LEN,FMT) \ | ||
54 | {\ | ||
55 | va_list args;\ | ||
56 | va_start(args, FMT);\ | ||
57 | LEN = vsprintf(PTR, FMT, args);\ | ||
58 | va_end(args);\ | ||
59 | *(PTR + LEN) = '\0';\ | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * Locking policy when using print buffers. | ||
64 | * | ||
65 | * 1) Routines of the form printbuf_XXX() rely on the caller to prevent | ||
66 | * simultaneous use of the print buffer(s) being manipulated. | ||
67 | * 2) tipc_printf() uses 'print_lock' to prevent simultaneous use of | ||
68 | * 'print_string' and to protect its print buffer(s). | ||
69 | * 3) TEE() uses 'print_lock' to protect its print buffer(s). | ||
70 | * 4) Routines of the form log_XXX() uses 'print_lock' to protect LOG. | ||
71 | */ | ||
72 | |||
73 | /** | ||
74 | * printbuf_init - initialize print buffer to empty | ||
75 | */ | ||
76 | |||
77 | void printbuf_init(struct print_buf *pb, char *raw, u32 sz) | ||
78 | { | ||
79 | if (!pb || !raw || (sz < (MAX_STRING + 1))) | ||
80 | return; | ||
81 | |||
82 | pb->crs = pb->buf = raw; | ||
83 | pb->size = sz; | ||
84 | pb->next = 0; | ||
85 | pb->buf[0] = 0; | ||
86 | pb->buf[sz-1] = ~0; | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * printbuf_reset - reinitialize print buffer to empty state | ||
91 | */ | ||
92 | |||
93 | void printbuf_reset(struct print_buf *pb) | ||
94 | { | ||
95 | if (pb && pb->buf) | ||
96 | printbuf_init(pb, pb->buf, pb->size); | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * printbuf_empty - test if print buffer is in empty state | ||
101 | */ | ||
102 | |||
103 | int printbuf_empty(struct print_buf *pb) | ||
104 | { | ||
105 | return (!pb || !pb->buf || (pb->crs == pb->buf)); | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * printbuf_validate - check for print buffer overflow | ||
110 | * | ||
111 | * Verifies that a print buffer has captured all data written to it. | ||
112 | * If data has been lost, linearize buffer and prepend an error message | ||
113 | * | ||
114 | * Returns length of print buffer data string (including trailing NULL) | ||
115 | */ | ||
116 | |||
117 | int printbuf_validate(struct print_buf *pb) | ||
118 | { | ||
119 | char *err = " *** PRINT BUFFER WRAPPED AROUND ***\n"; | ||
120 | char *cp_buf; | ||
121 | struct print_buf cb; | ||
122 | |||
123 | if (!pb || !pb->buf) | ||
124 | return 0; | ||
125 | |||
126 | if (pb->buf[pb->size - 1] == '\0') { | ||
127 | cp_buf = kmalloc(pb->size, GFP_ATOMIC); | ||
128 | if (cp_buf != NULL){ | ||
129 | printbuf_init(&cb, cp_buf, pb->size); | ||
130 | printbuf_move(&cb, pb); | ||
131 | printbuf_move(pb, &cb); | ||
132 | kfree(cp_buf); | ||
133 | memcpy(pb->buf, err, strlen(err)); | ||
134 | } else { | ||
135 | printbuf_reset(pb); | ||
136 | tipc_printf(pb, err); | ||
137 | } | ||
138 | } | ||
139 | return (pb->crs - pb->buf + 1); | ||
140 | } | ||
141 | |||
142 | /** | ||
143 | * printbuf_move - move print buffer contents to another print buffer | ||
144 | * | ||
145 | * Current contents of destination print buffer (if any) are discarded. | ||
146 | * Source print buffer becomes empty if a successful move occurs. | ||
147 | */ | ||
148 | |||
149 | void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from) | ||
150 | { | ||
151 | int len; | ||
152 | |||
153 | /* Handle the cases where contents can't be moved */ | ||
154 | |||
155 | if (!pb_to || !pb_to->buf) | ||
156 | return; | ||
157 | |||
158 | if (!pb_from || !pb_from->buf) { | ||
159 | printbuf_reset(pb_to); | ||
160 | return; | ||
161 | } | ||
162 | |||
163 | if (pb_to->size < pb_from->size) { | ||
164 | printbuf_reset(pb_to); | ||
165 | tipc_printf(pb_to, "*** PRINT BUFFER OVERFLOW ***"); | ||
166 | return; | ||
167 | } | ||
168 | |||
169 | /* Copy data from char after cursor to end (if used) */ | ||
170 | len = pb_from->buf + pb_from->size - pb_from->crs - 2; | ||
171 | if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) { | ||
172 | strcpy(pb_to->buf, pb_from->crs + 1); | ||
173 | pb_to->crs = pb_to->buf + len; | ||
174 | } else | ||
175 | pb_to->crs = pb_to->buf; | ||
176 | |||
177 | /* Copy data from start to cursor (always) */ | ||
178 | len = pb_from->crs - pb_from->buf; | ||
179 | strcpy(pb_to->crs, pb_from->buf); | ||
180 | pb_to->crs += len; | ||
181 | |||
182 | printbuf_reset(pb_from); | ||
183 | } | ||
184 | |||
185 | /** | ||
186 | * tipc_printf - append formatted output to print buffer chain | ||
187 | */ | ||
188 | |||
189 | void tipc_printf(struct print_buf *pb, const char *fmt, ...) | ||
190 | { | ||
191 | int chars_to_add; | ||
192 | int chars_left; | ||
193 | char save_char; | ||
194 | struct print_buf *pb_next; | ||
195 | |||
196 | spin_lock_bh(&print_lock); | ||
197 | FORMAT(print_string, chars_to_add, fmt); | ||
198 | if (chars_to_add >= MAX_STRING) | ||
199 | strcpy(print_string, "*** STRING TOO LONG ***"); | ||
200 | |||
201 | while (pb) { | ||
202 | if (pb == CONS) | ||
203 | printk(print_string); | ||
204 | else if (pb->buf) { | ||
205 | chars_left = pb->buf + pb->size - pb->crs - 1; | ||
206 | if (chars_to_add <= chars_left) { | ||
207 | strcpy(pb->crs, print_string); | ||
208 | pb->crs += chars_to_add; | ||
209 | } else { | ||
210 | strcpy(pb->buf, print_string + chars_left); | ||
211 | save_char = print_string[chars_left]; | ||
212 | print_string[chars_left] = 0; | ||
213 | strcpy(pb->crs, print_string); | ||
214 | print_string[chars_left] = save_char; | ||
215 | pb->crs = pb->buf + chars_to_add - chars_left; | ||
216 | } | ||
217 | } | ||
218 | pb_next = pb->next; | ||
219 | pb->next = 0; | ||
220 | pb = pb_next; | ||
221 | } | ||
222 | spin_unlock_bh(&print_lock); | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * TEE - perform next output operation on both print buffers | ||
227 | */ | ||
228 | |||
229 | struct print_buf *TEE(struct print_buf *b0, struct print_buf *b1) | ||
230 | { | ||
231 | struct print_buf *pb = b0; | ||
232 | |||
233 | if (!b0 || (b0 == b1)) | ||
234 | return b1; | ||
235 | if (!b1) | ||
236 | return b0; | ||
237 | |||
238 | spin_lock_bh(&print_lock); | ||
239 | while (pb->next) { | ||
240 | if ((pb->next == b1) || (pb->next == b0)) | ||
241 | pb->next = pb->next->next; | ||
242 | else | ||
243 | pb = pb->next; | ||
244 | } | ||
245 | pb->next = b1; | ||
246 | spin_unlock_bh(&print_lock); | ||
247 | return b0; | ||
248 | } | ||
249 | |||
250 | /** | ||
251 | * print_to_console - write string of bytes to console in multiple chunks | ||
252 | */ | ||
253 | |||
254 | static void print_to_console(char *crs, int len) | ||
255 | { | ||
256 | int rest = len; | ||
257 | |||
258 | while (rest > 0) { | ||
259 | int sz = rest < MAX_STRING ? rest : MAX_STRING; | ||
260 | char c = crs[sz]; | ||
261 | |||
262 | crs[sz] = 0; | ||
263 | printk((const char *)crs); | ||
264 | crs[sz] = c; | ||
265 | rest -= sz; | ||
266 | crs += sz; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | /** | ||
271 | * printbuf_dump - write print buffer contents to console | ||
272 | */ | ||
273 | |||
274 | static void printbuf_dump(struct print_buf *pb) | ||
275 | { | ||
276 | int len; | ||
277 | |||
278 | /* Dump print buffer from char after cursor to end (if used) */ | ||
279 | len = pb->buf + pb->size - pb->crs - 2; | ||
280 | if ((pb->buf[pb->size - 1] == 0) && (len > 0)) | ||
281 | print_to_console(pb->crs + 1, len); | ||
282 | |||
283 | /* Dump print buffer from start to cursor (always) */ | ||
284 | len = pb->crs - pb->buf; | ||
285 | print_to_console(pb->buf, len); | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * tipc_dump - dump non-console print buffer(s) to console | ||
290 | */ | ||
291 | |||
292 | void tipc_dump(struct print_buf *pb, const char *fmt, ...) | ||
293 | { | ||
294 | int len; | ||
295 | |||
296 | spin_lock_bh(&print_lock); | ||
297 | FORMAT(CONS->buf, len, fmt); | ||
298 | printk(CONS->buf); | ||
299 | |||
300 | for (; pb; pb = pb->next) { | ||
301 | if (pb == CONS) | ||
302 | continue; | ||
303 | printk("\n---- Start of dump,%s log ----\n\n", | ||
304 | (pb == LOG) ? "global" : "local"); | ||
305 | printbuf_dump(pb); | ||
306 | printbuf_reset(pb); | ||
307 | printk("\n-------- End of dump --------\n"); | ||
308 | } | ||
309 | spin_unlock_bh(&print_lock); | ||
310 | } | ||
311 | |||
312 | /** | ||
313 | * log_stop - free up TIPC log print buffer | ||
314 | */ | ||
315 | |||
316 | void log_stop(void) | ||
317 | { | ||
318 | spin_lock_bh(&print_lock); | ||
319 | if (LOG->buf) { | ||
320 | kfree(LOG->buf); | ||
321 | LOG->buf = NULL; | ||
322 | } | ||
323 | spin_unlock_bh(&print_lock); | ||
324 | } | ||
325 | |||
326 | /** | ||
327 | * log_reinit - set TIPC log print buffer to specified size | ||
328 | */ | ||
329 | |||
330 | void log_reinit(int log_size) | ||
331 | { | ||
332 | log_stop(); | ||
333 | |||
334 | if (log_size) { | ||
335 | if (log_size <= MAX_STRING) | ||
336 | log_size = MAX_STRING + 1; | ||
337 | spin_lock_bh(&print_lock); | ||
338 | printbuf_init(LOG, kmalloc(log_size, GFP_ATOMIC), log_size); | ||
339 | spin_unlock_bh(&print_lock); | ||
340 | } | ||
341 | } | ||
342 | |||
343 | /** | ||
344 | * log_resize - reconfigure size of TIPC log buffer | ||
345 | */ | ||
346 | |||
347 | struct sk_buff *log_resize(const void *req_tlv_area, int req_tlv_space) | ||
348 | { | ||
349 | u32 value; | ||
350 | |||
351 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
352 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
353 | |||
354 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
355 | value = ntohl(value); | ||
356 | if (value != delimit(value, 0, 32768)) | ||
357 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
358 | " (log size must be 0-32768)"); | ||
359 | log_reinit(value); | ||
360 | return cfg_reply_none(); | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * log_dump - capture TIPC log buffer contents in configuration message | ||
365 | */ | ||
366 | |||
367 | struct sk_buff *log_dump(void) | ||
368 | { | ||
369 | struct sk_buff *reply; | ||
370 | |||
371 | spin_lock_bh(&print_lock); | ||
372 | if (!LOG->buf) | ||
373 | reply = cfg_reply_ultra_string("log not activated\n"); | ||
374 | else if (printbuf_empty(LOG)) | ||
375 | reply = cfg_reply_ultra_string("log is empty\n"); | ||
376 | else { | ||
377 | struct tlv_desc *rep_tlv; | ||
378 | struct print_buf pb; | ||
379 | int str_len; | ||
380 | |||
381 | str_len = min(LOG->size, 32768u); | ||
382 | reply = cfg_reply_alloc(TLV_SPACE(str_len)); | ||
383 | if (reply) { | ||
384 | rep_tlv = (struct tlv_desc *)reply->data; | ||
385 | printbuf_init(&pb, TLV_DATA(rep_tlv), str_len); | ||
386 | printbuf_move(&pb, LOG); | ||
387 | str_len = strlen(TLV_DATA(rep_tlv)) + 1; | ||
388 | skb_put(reply, TLV_SPACE(str_len)); | ||
389 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | ||
390 | } | ||
391 | } | ||
392 | spin_unlock_bh(&print_lock); | ||
393 | return reply; | ||
394 | } | ||
395 | |||
diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h new file mode 100644 index 000000000000..c6b2a64c224f --- /dev/null +++ b/net/tipc/dbg.h | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * net/tipc/dbg.h: Include file for TIPC print buffer routines | ||
3 | * | ||
4 | * Copyright (c) 1997-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_DBG_H | ||
38 | #define _TIPC_DBG_H | ||
39 | |||
40 | struct print_buf { | ||
41 | char *buf; | ||
42 | u32 size; | ||
43 | char *crs; | ||
44 | struct print_buf *next; | ||
45 | }; | ||
46 | |||
47 | void printbuf_init(struct print_buf *pb, char *buf, u32 sz); | ||
48 | void printbuf_reset(struct print_buf *pb); | ||
49 | int printbuf_empty(struct print_buf *pb); | ||
50 | int printbuf_validate(struct print_buf *pb); | ||
51 | void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from); | ||
52 | |||
53 | void log_reinit(int log_size); | ||
54 | void log_stop(void); | ||
55 | |||
56 | struct sk_buff *log_resize(const void *req_tlv_area, int req_tlv_space); | ||
57 | struct sk_buff *log_dump(void); | ||
58 | |||
59 | #endif | ||
diff --git a/net/tipc/discover.c b/net/tipc/discover.c new file mode 100644 index 000000000000..b106ef1621cc --- /dev/null +++ b/net/tipc/discover.c | |||
@@ -0,0 +1,318 @@ | |||
1 | /* | ||
2 | * net/tipc/discover.c | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "dbg.h" | ||
39 | #include "link.h" | ||
40 | #include "zone.h" | ||
41 | #include "discover.h" | ||
42 | #include "port.h" | ||
43 | #include "name_table.h" | ||
44 | |||
45 | #define TIPC_LINK_REQ_INIT 125 /* min delay during bearer start up */ | ||
46 | #define TIPC_LINK_REQ_FAST 2000 /* normal delay if bearer has no links */ | ||
47 | #define TIPC_LINK_REQ_SLOW 600000 /* normal delay if bearer has links */ | ||
48 | |||
49 | #if 0 | ||
50 | #define GET_NODE_INFO 300 | ||
51 | #define GET_NODE_INFO_RESULT 301 | ||
52 | #define FORWARD_LINK_PROBE 302 | ||
53 | #define LINK_REQUEST_REJECTED 303 | ||
54 | #define LINK_REQUEST_ACCEPTED 304 | ||
55 | #define DROP_LINK_REQUEST 305 | ||
56 | #define CHECK_LINK_COUNT 306 | ||
57 | #endif | ||
58 | |||
59 | /* | ||
60 | * TODO: Most of the inter-cluster setup stuff should be | ||
61 | * rewritten, and be made conformant with specification. | ||
62 | */ | ||
63 | |||
64 | |||
65 | /** | ||
66 | * struct link_req - information about an ongoing link setup request | ||
67 | * @bearer: bearer issuing requests | ||
68 | * @dest: destination address for request messages | ||
69 | * @buf: request message to be (repeatedly) sent | ||
70 | * @timer: timer governing period between requests | ||
71 | * @timer_intv: current interval between requests (in ms) | ||
72 | */ | ||
73 | struct link_req { | ||
74 | struct bearer *bearer; | ||
75 | struct tipc_media_addr dest; | ||
76 | struct sk_buff *buf; | ||
77 | struct timer_list timer; | ||
78 | unsigned int timer_intv; | ||
79 | }; | ||
80 | |||
81 | |||
82 | #if 0 | ||
83 | int disc_create_link(const struct tipc_link_create *argv) | ||
84 | { | ||
85 | /* | ||
86 | * Code for inter cluster link setup here | ||
87 | */ | ||
88 | return TIPC_OK; | ||
89 | } | ||
90 | #endif | ||
91 | |||
92 | /* | ||
93 | * disc_lost_link(): A link has lost contact | ||
94 | */ | ||
95 | |||
96 | void disc_link_event(u32 addr, char *name, int up) | ||
97 | { | ||
98 | if (in_own_cluster(addr)) | ||
99 | return; | ||
100 | /* | ||
101 | * Code for inter cluster link setup here | ||
102 | */ | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * disc_init_msg - initialize a link setup message | ||
107 | * @type: message type (request or response) | ||
108 | * @req_links: number of links associated with message | ||
109 | * @dest_domain: network domain of node(s) which should respond to message | ||
110 | * @b_ptr: ptr to bearer issuing message | ||
111 | */ | ||
112 | |||
113 | struct sk_buff *disc_init_msg(u32 type, | ||
114 | u32 req_links, | ||
115 | u32 dest_domain, | ||
116 | struct bearer *b_ptr) | ||
117 | { | ||
118 | struct sk_buff *buf = buf_acquire(DSC_H_SIZE); | ||
119 | struct tipc_msg *msg; | ||
120 | |||
121 | if (buf) { | ||
122 | msg = buf_msg(buf); | ||
123 | msg_init(msg, LINK_CONFIG, type, TIPC_OK, DSC_H_SIZE, | ||
124 | dest_domain); | ||
125 | msg_set_non_seq(msg); | ||
126 | msg_set_req_links(msg, req_links); | ||
127 | msg_set_dest_domain(msg, dest_domain); | ||
128 | msg_set_bc_netid(msg, tipc_net_id); | ||
129 | msg_set_media_addr(msg, &b_ptr->publ.addr); | ||
130 | } | ||
131 | return buf; | ||
132 | } | ||
133 | |||
134 | /** | ||
135 | * disc_recv_msg - handle incoming link setup message (request or response) | ||
136 | * @buf: buffer containing message | ||
137 | */ | ||
138 | |||
139 | void disc_recv_msg(struct sk_buff *buf) | ||
140 | { | ||
141 | struct bearer *b_ptr = (struct bearer *)TIPC_SKB_CB(buf)->handle; | ||
142 | struct link *link; | ||
143 | struct tipc_media_addr media_addr; | ||
144 | struct tipc_msg *msg = buf_msg(buf); | ||
145 | u32 dest = msg_dest_domain(msg); | ||
146 | u32 orig = msg_prevnode(msg); | ||
147 | u32 net_id = msg_bc_netid(msg); | ||
148 | u32 type = msg_type(msg); | ||
149 | |||
150 | msg_get_media_addr(msg,&media_addr); | ||
151 | msg_dbg(msg, "RECV:"); | ||
152 | buf_discard(buf); | ||
153 | |||
154 | if (net_id != tipc_net_id) | ||
155 | return; | ||
156 | if (!addr_domain_valid(dest)) | ||
157 | return; | ||
158 | if (!addr_node_valid(orig)) | ||
159 | return; | ||
160 | if (orig == tipc_own_addr) | ||
161 | return; | ||
162 | if (!in_scope(dest, tipc_own_addr)) | ||
163 | return; | ||
164 | if (is_slave(tipc_own_addr) && is_slave(orig)) | ||
165 | return; | ||
166 | if (is_slave(orig) && !in_own_cluster(orig)) | ||
167 | return; | ||
168 | if (in_own_cluster(orig)) { | ||
169 | /* Always accept link here */ | ||
170 | struct sk_buff *rbuf; | ||
171 | struct tipc_media_addr *addr; | ||
172 | struct node *n_ptr = node_find(orig); | ||
173 | int link_up; | ||
174 | dbg(" in own cluster\n"); | ||
175 | if (n_ptr == NULL) { | ||
176 | n_ptr = node_create(orig); | ||
177 | } | ||
178 | if (n_ptr == NULL) { | ||
179 | warn("Memory squeeze; Failed to create node\n"); | ||
180 | return; | ||
181 | } | ||
182 | spin_lock_bh(&n_ptr->lock); | ||
183 | link = n_ptr->links[b_ptr->identity]; | ||
184 | if (!link) { | ||
185 | dbg("creating link\n"); | ||
186 | link = link_create(b_ptr, orig, &media_addr); | ||
187 | if (!link) { | ||
188 | spin_unlock_bh(&n_ptr->lock); | ||
189 | return; | ||
190 | } | ||
191 | } | ||
192 | addr = &link->media_addr; | ||
193 | if (memcmp(addr, &media_addr, sizeof(*addr))) { | ||
194 | char addr_string[16]; | ||
195 | |||
196 | warn("New bearer address for %s\n", | ||
197 | addr_string_fill(addr_string, orig)); | ||
198 | memcpy(addr, &media_addr, sizeof(*addr)); | ||
199 | link_reset(link); | ||
200 | } | ||
201 | link_up = link_is_up(link); | ||
202 | spin_unlock_bh(&n_ptr->lock); | ||
203 | if ((type == DSC_RESP_MSG) || link_up) | ||
204 | return; | ||
205 | rbuf = disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr); | ||
206 | if (rbuf != NULL) { | ||
207 | msg_dbg(buf_msg(rbuf),"SEND:"); | ||
208 | b_ptr->media->send_msg(rbuf, &b_ptr->publ, &media_addr); | ||
209 | buf_discard(rbuf); | ||
210 | } | ||
211 | } | ||
212 | } | ||
213 | |||
214 | /** | ||
215 | * disc_stop_link_req - stop sending periodic link setup requests | ||
216 | * @req: ptr to link request structure | ||
217 | */ | ||
218 | |||
219 | void disc_stop_link_req(struct link_req *req) | ||
220 | { | ||
221 | if (!req) | ||
222 | return; | ||
223 | |||
224 | k_cancel_timer(&req->timer); | ||
225 | k_term_timer(&req->timer); | ||
226 | buf_discard(req->buf); | ||
227 | kfree(req); | ||
228 | } | ||
229 | |||
230 | /** | ||
231 | * disc_update_link_req - update frequency of periodic link setup requests | ||
232 | * @req: ptr to link request structure | ||
233 | */ | ||
234 | |||
235 | void disc_update_link_req(struct link_req *req) | ||
236 | { | ||
237 | if (!req) | ||
238 | return; | ||
239 | |||
240 | if (req->timer_intv == TIPC_LINK_REQ_SLOW) { | ||
241 | if (!req->bearer->nodes.count) { | ||
242 | req->timer_intv = TIPC_LINK_REQ_FAST; | ||
243 | k_start_timer(&req->timer, req->timer_intv); | ||
244 | } | ||
245 | } else if (req->timer_intv == TIPC_LINK_REQ_FAST) { | ||
246 | if (req->bearer->nodes.count) { | ||
247 | req->timer_intv = TIPC_LINK_REQ_SLOW; | ||
248 | k_start_timer(&req->timer, req->timer_intv); | ||
249 | } | ||
250 | } else { | ||
251 | /* leave timer "as is" if haven't yet reached a "normal" rate */ | ||
252 | } | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * disc_timeout - send a periodic link setup request | ||
257 | * @req: ptr to link request structure | ||
258 | * | ||
259 | * Called whenever a link setup request timer associated with a bearer expires. | ||
260 | */ | ||
261 | |||
262 | static void disc_timeout(struct link_req *req) | ||
263 | { | ||
264 | spin_lock_bh(&req->bearer->publ.lock); | ||
265 | |||
266 | req->bearer->media->send_msg(req->buf, &req->bearer->publ, &req->dest); | ||
267 | |||
268 | if ((req->timer_intv == TIPC_LINK_REQ_SLOW) || | ||
269 | (req->timer_intv == TIPC_LINK_REQ_FAST)) { | ||
270 | /* leave timer interval "as is" if already at a "normal" rate */ | ||
271 | } else { | ||
272 | req->timer_intv *= 2; | ||
273 | if (req->timer_intv > TIPC_LINK_REQ_SLOW) | ||
274 | req->timer_intv = TIPC_LINK_REQ_SLOW; | ||
275 | if ((req->timer_intv == TIPC_LINK_REQ_FAST) && | ||
276 | (req->bearer->nodes.count)) | ||
277 | req->timer_intv = TIPC_LINK_REQ_SLOW; | ||
278 | } | ||
279 | k_start_timer(&req->timer, req->timer_intv); | ||
280 | |||
281 | spin_unlock_bh(&req->bearer->publ.lock); | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * disc_init_link_req - start sending periodic link setup requests | ||
286 | * @b_ptr: ptr to bearer issuing requests | ||
287 | * @dest: destination address for request messages | ||
288 | * @dest_domain: network domain of node(s) which should respond to message | ||
289 | * @req_links: max number of desired links | ||
290 | * | ||
291 | * Returns pointer to link request structure, or NULL if unable to create. | ||
292 | */ | ||
293 | |||
294 | struct link_req *disc_init_link_req(struct bearer *b_ptr, | ||
295 | const struct tipc_media_addr *dest, | ||
296 | u32 dest_domain, | ||
297 | u32 req_links) | ||
298 | { | ||
299 | struct link_req *req; | ||
300 | |||
301 | req = (struct link_req *)kmalloc(sizeof(*req), GFP_ATOMIC); | ||
302 | if (!req) | ||
303 | return NULL; | ||
304 | |||
305 | req->buf = disc_init_msg(DSC_REQ_MSG, req_links, dest_domain, b_ptr); | ||
306 | if (!req->buf) { | ||
307 | kfree(req); | ||
308 | return NULL; | ||
309 | } | ||
310 | |||
311 | memcpy(&req->dest, dest, sizeof(*dest)); | ||
312 | req->bearer = b_ptr; | ||
313 | req->timer_intv = TIPC_LINK_REQ_INIT; | ||
314 | k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); | ||
315 | k_start_timer(&req->timer, req->timer_intv); | ||
316 | return req; | ||
317 | } | ||
318 | |||
diff --git a/net/tipc/discover.h b/net/tipc/discover.h new file mode 100644 index 000000000000..2a6114d91626 --- /dev/null +++ b/net/tipc/discover.h | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * net/tipc/discover.h | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_DISCOVER_H | ||
38 | #define _TIPC_DISCOVER_H | ||
39 | |||
40 | #include <linux/tipc.h> | ||
41 | |||
42 | struct link_req; | ||
43 | |||
44 | struct link_req *disc_init_link_req(struct bearer *b_ptr, | ||
45 | const struct tipc_media_addr *dest, | ||
46 | u32 dest_domain, | ||
47 | u32 req_links); | ||
48 | void disc_update_link_req(struct link_req *req); | ||
49 | void disc_stop_link_req(struct link_req *req); | ||
50 | |||
51 | void disc_recv_msg(struct sk_buff *buf); | ||
52 | |||
53 | void disc_link_event(u32 addr, char *name, int up); | ||
54 | #if 0 | ||
55 | int disc_create_link(const struct tipc_link_create *argv); | ||
56 | #endif | ||
57 | |||
58 | #endif | ||
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c new file mode 100644 index 000000000000..34d0462db3aa --- /dev/null +++ b/net/tipc/eth_media.c | |||
@@ -0,0 +1,299 @@ | |||
1 | /* | ||
2 | * net/tipc/eth_media.c: Ethernet bearer support for TIPC | ||
3 | * | ||
4 | * Copyright (c) 2001-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include <net/tipc/tipc.h> | ||
38 | #include <net/tipc/tipc_bearer.h> | ||
39 | #include <net/tipc/tipc_msg.h> | ||
40 | #include <linux/netdevice.h> | ||
41 | #include <linux/version.h> | ||
42 | |||
43 | #define MAX_ETH_BEARERS 2 | ||
44 | #define TIPC_PROTOCOL 0x88ca | ||
45 | #define ETH_LINK_PRIORITY 10 | ||
46 | #define ETH_LINK_TOLERANCE TIPC_DEF_LINK_TOL | ||
47 | |||
48 | |||
49 | /** | ||
50 | * struct eth_bearer - Ethernet bearer data structure | ||
51 | * @bearer: ptr to associated "generic" bearer structure | ||
52 | * @dev: ptr to associated Ethernet network device | ||
53 | * @tipc_packet_type: used in binding TIPC to Ethernet driver | ||
54 | */ | ||
55 | |||
56 | struct eth_bearer { | ||
57 | struct tipc_bearer *bearer; | ||
58 | struct net_device *dev; | ||
59 | struct packet_type tipc_packet_type; | ||
60 | }; | ||
61 | |||
62 | static struct eth_bearer eth_bearers[MAX_ETH_BEARERS]; | ||
63 | static int eth_started = 0; | ||
64 | static struct notifier_block notifier; | ||
65 | |||
66 | /** | ||
67 | * send_msg - send a TIPC message out over an Ethernet interface | ||
68 | */ | ||
69 | |||
70 | static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr, | ||
71 | struct tipc_media_addr *dest) | ||
72 | { | ||
73 | struct sk_buff *clone; | ||
74 | struct net_device *dev; | ||
75 | |||
76 | clone = skb_clone(buf, GFP_ATOMIC); | ||
77 | if (clone) { | ||
78 | clone->nh.raw = clone->data; | ||
79 | dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev; | ||
80 | clone->dev = dev; | ||
81 | dev->hard_header(clone, dev, TIPC_PROTOCOL, | ||
82 | &dest->dev_addr.eth_addr, | ||
83 | dev->dev_addr, clone->len); | ||
84 | dev_queue_xmit(clone); | ||
85 | } | ||
86 | return TIPC_OK; | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * recv_msg - handle incoming TIPC message from an Ethernet interface | ||
91 | * | ||
92 | * Routine truncates any Ethernet padding/CRC appended to the message, | ||
93 | * and ensures message size matches actual length | ||
94 | */ | ||
95 | |||
96 | static int recv_msg(struct sk_buff *buf, struct net_device *dev, | ||
97 | struct packet_type *pt, struct net_device *orig_dev) | ||
98 | { | ||
99 | struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv; | ||
100 | u32 size; | ||
101 | |||
102 | if (likely(eb_ptr->bearer)) { | ||
103 | size = msg_size((struct tipc_msg *)buf->data); | ||
104 | skb_trim(buf, size); | ||
105 | if (likely(buf->len == size)) { | ||
106 | buf->next = NULL; | ||
107 | tipc_recv_msg(buf, eb_ptr->bearer); | ||
108 | } else { | ||
109 | kfree_skb(buf); | ||
110 | } | ||
111 | } else { | ||
112 | kfree_skb(buf); | ||
113 | } | ||
114 | return TIPC_OK; | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * enable_bearer - attach TIPC bearer to an Ethernet interface | ||
119 | */ | ||
120 | |||
121 | static int enable_bearer(struct tipc_bearer *tb_ptr) | ||
122 | { | ||
123 | struct net_device *dev = dev_base; | ||
124 | struct eth_bearer *eb_ptr = ð_bearers[0]; | ||
125 | struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS]; | ||
126 | char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; | ||
127 | |||
128 | /* Find device with specified name */ | ||
129 | |||
130 | while (dev && dev->name && | ||
131 | (memcmp(dev->name, driver_name, strlen(dev->name)))) { | ||
132 | dev = dev->next; | ||
133 | } | ||
134 | if (!dev) | ||
135 | return -ENODEV; | ||
136 | |||
137 | /* Find Ethernet bearer for device (or create one) */ | ||
138 | |||
139 | for (;(eb_ptr != stop) && eb_ptr->dev && (eb_ptr->dev != dev); eb_ptr++); | ||
140 | if (eb_ptr == stop) | ||
141 | return -EDQUOT; | ||
142 | if (!eb_ptr->dev) { | ||
143 | eb_ptr->dev = dev; | ||
144 | eb_ptr->tipc_packet_type.type = __constant_htons(TIPC_PROTOCOL); | ||
145 | eb_ptr->tipc_packet_type.dev = dev; | ||
146 | eb_ptr->tipc_packet_type.func = recv_msg; | ||
147 | eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr; | ||
148 | INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list)); | ||
149 | dev_hold(dev); | ||
150 | dev_add_pack(&eb_ptr->tipc_packet_type); | ||
151 | } | ||
152 | |||
153 | /* Associate TIPC bearer with Ethernet bearer */ | ||
154 | |||
155 | eb_ptr->bearer = tb_ptr; | ||
156 | tb_ptr->usr_handle = (void *)eb_ptr; | ||
157 | tb_ptr->mtu = dev->mtu; | ||
158 | tb_ptr->blocked = 0; | ||
159 | tb_ptr->addr.type = htonl(TIPC_MEDIA_TYPE_ETH); | ||
160 | memcpy(&tb_ptr->addr.dev_addr, &dev->dev_addr, ETH_ALEN); | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * disable_bearer - detach TIPC bearer from an Ethernet interface | ||
166 | * | ||
167 | * We really should do dev_remove_pack() here, but this function can not be | ||
168 | * called at tasklet level. => Use eth_bearer->bearer as a flag to throw away | ||
169 | * incoming buffers, & postpone dev_remove_pack() to eth_media_stop() on exit. | ||
170 | */ | ||
171 | |||
172 | static void disable_bearer(struct tipc_bearer *tb_ptr) | ||
173 | { | ||
174 | ((struct eth_bearer *)tb_ptr->usr_handle)->bearer = 0; | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * recv_notification - handle device updates from OS | ||
179 | * | ||
180 | * Change the state of the Ethernet bearer (if any) associated with the | ||
181 | * specified device. | ||
182 | */ | ||
183 | |||
184 | static int recv_notification(struct notifier_block *nb, unsigned long evt, | ||
185 | void *dv) | ||
186 | { | ||
187 | struct net_device *dev = (struct net_device *)dv; | ||
188 | struct eth_bearer *eb_ptr = ð_bearers[0]; | ||
189 | struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS]; | ||
190 | |||
191 | while ((eb_ptr->dev != dev)) { | ||
192 | if (++eb_ptr == stop) | ||
193 | return NOTIFY_DONE; /* couldn't find device */ | ||
194 | } | ||
195 | if (!eb_ptr->bearer) | ||
196 | return NOTIFY_DONE; /* bearer had been disabled */ | ||
197 | |||
198 | eb_ptr->bearer->mtu = dev->mtu; | ||
199 | |||
200 | switch (evt) { | ||
201 | case NETDEV_CHANGE: | ||
202 | if (netif_carrier_ok(dev)) | ||
203 | tipc_continue(eb_ptr->bearer); | ||
204 | else | ||
205 | tipc_block_bearer(eb_ptr->bearer->name); | ||
206 | break; | ||
207 | case NETDEV_UP: | ||
208 | tipc_continue(eb_ptr->bearer); | ||
209 | break; | ||
210 | case NETDEV_DOWN: | ||
211 | tipc_block_bearer(eb_ptr->bearer->name); | ||
212 | break; | ||
213 | case NETDEV_CHANGEMTU: | ||
214 | case NETDEV_CHANGEADDR: | ||
215 | tipc_block_bearer(eb_ptr->bearer->name); | ||
216 | tipc_continue(eb_ptr->bearer); | ||
217 | break; | ||
218 | case NETDEV_UNREGISTER: | ||
219 | case NETDEV_CHANGENAME: | ||
220 | tipc_disable_bearer(eb_ptr->bearer->name); | ||
221 | break; | ||
222 | } | ||
223 | return NOTIFY_OK; | ||
224 | } | ||
225 | |||
226 | /** | ||
227 | * eth_addr2str - convert Ethernet address to string | ||
228 | */ | ||
229 | |||
230 | static char *eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size) | ||
231 | { | ||
232 | unchar *addr = (unchar *)&a->dev_addr; | ||
233 | |||
234 | if (str_size < 18) | ||
235 | *str_buf = '\0'; | ||
236 | else | ||
237 | sprintf(str_buf, "%02x:%02x:%02x:%02x:%02x:%02x", | ||
238 | addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); | ||
239 | return str_buf; | ||
240 | } | ||
241 | |||
242 | /** | ||
243 | * eth_media_start - activate Ethernet bearer support | ||
244 | * | ||
245 | * Register Ethernet media type with TIPC bearer code. Also register | ||
246 | * with OS for notifications about device state changes. | ||
247 | */ | ||
248 | |||
249 | int eth_media_start(void) | ||
250 | { | ||
251 | struct tipc_media_addr bcast_addr; | ||
252 | int res; | ||
253 | |||
254 | if (eth_started) | ||
255 | return -EINVAL; | ||
256 | |||
257 | memset(&bcast_addr, 0xff, sizeof(bcast_addr)); | ||
258 | memset(eth_bearers, 0, sizeof(eth_bearers)); | ||
259 | |||
260 | res = tipc_register_media(TIPC_MEDIA_TYPE_ETH, "eth", | ||
261 | enable_bearer, disable_bearer, send_msg, | ||
262 | eth_addr2str, &bcast_addr, ETH_LINK_PRIORITY, | ||
263 | ETH_LINK_TOLERANCE, TIPC_DEF_LINK_WIN); | ||
264 | if (res) | ||
265 | return res; | ||
266 | |||
267 | notifier.notifier_call = &recv_notification; | ||
268 | notifier.priority = 0; | ||
269 | res = register_netdevice_notifier(¬ifier); | ||
270 | if (!res) | ||
271 | eth_started = 1; | ||
272 | return res; | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * eth_media_stop - deactivate Ethernet bearer support | ||
277 | */ | ||
278 | |||
279 | void eth_media_stop(void) | ||
280 | { | ||
281 | int i; | ||
282 | |||
283 | if (!eth_started) | ||
284 | return; | ||
285 | |||
286 | unregister_netdevice_notifier(¬ifier); | ||
287 | for (i = 0; i < MAX_ETH_BEARERS ; i++) { | ||
288 | if (eth_bearers[i].bearer) { | ||
289 | eth_bearers[i].bearer->blocked = 1; | ||
290 | eth_bearers[i].bearer = 0; | ||
291 | } | ||
292 | if (eth_bearers[i].dev) { | ||
293 | dev_remove_pack(ð_bearers[i].tipc_packet_type); | ||
294 | dev_put(eth_bearers[i].dev); | ||
295 | } | ||
296 | } | ||
297 | memset(ð_bearers, 0, sizeof(eth_bearers)); | ||
298 | eth_started = 0; | ||
299 | } | ||
diff --git a/net/tipc/handler.c b/net/tipc/handler.c new file mode 100644 index 000000000000..f320010f8a65 --- /dev/null +++ b/net/tipc/handler.c | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | * net/tipc/handler.c: TIPC signal handling | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | |||
39 | struct queue_item { | ||
40 | struct list_head next_signal; | ||
41 | void (*handler) (unsigned long); | ||
42 | unsigned long data; | ||
43 | }; | ||
44 | |||
45 | static kmem_cache_t *tipc_queue_item_cache; | ||
46 | static struct list_head signal_queue_head; | ||
47 | static spinlock_t qitem_lock = SPIN_LOCK_UNLOCKED; | ||
48 | static int handler_enabled = 0; | ||
49 | |||
50 | static void process_signal_queue(unsigned long dummy); | ||
51 | |||
52 | static DECLARE_TASKLET_DISABLED(tipc_tasklet, process_signal_queue, 0); | ||
53 | |||
54 | |||
55 | unsigned int k_signal(Handler routine, unsigned long argument) | ||
56 | { | ||
57 | struct queue_item *item; | ||
58 | |||
59 | if (!handler_enabled) { | ||
60 | err("Signal request ignored by handler\n"); | ||
61 | return -ENOPROTOOPT; | ||
62 | } | ||
63 | |||
64 | spin_lock_bh(&qitem_lock); | ||
65 | item = kmem_cache_alloc(tipc_queue_item_cache, GFP_ATOMIC); | ||
66 | if (!item) { | ||
67 | err("Signal queue out of memory\n"); | ||
68 | spin_unlock_bh(&qitem_lock); | ||
69 | return -ENOMEM; | ||
70 | } | ||
71 | item->handler = routine; | ||
72 | item->data = argument; | ||
73 | list_add_tail(&item->next_signal, &signal_queue_head); | ||
74 | spin_unlock_bh(&qitem_lock); | ||
75 | tasklet_schedule(&tipc_tasklet); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static void process_signal_queue(unsigned long dummy) | ||
80 | { | ||
81 | struct queue_item *__volatile__ item; | ||
82 | struct list_head *l, *n; | ||
83 | |||
84 | spin_lock_bh(&qitem_lock); | ||
85 | list_for_each_safe(l, n, &signal_queue_head) { | ||
86 | item = list_entry(l, struct queue_item, next_signal); | ||
87 | list_del(&item->next_signal); | ||
88 | spin_unlock_bh(&qitem_lock); | ||
89 | item->handler(item->data); | ||
90 | spin_lock_bh(&qitem_lock); | ||
91 | kmem_cache_free(tipc_queue_item_cache, item); | ||
92 | } | ||
93 | spin_unlock_bh(&qitem_lock); | ||
94 | } | ||
95 | |||
96 | int handler_start(void) | ||
97 | { | ||
98 | tipc_queue_item_cache = | ||
99 | kmem_cache_create("tipc_queue_items", sizeof(struct queue_item), | ||
100 | 0, SLAB_HWCACHE_ALIGN, NULL, NULL); | ||
101 | if (!tipc_queue_item_cache) | ||
102 | return -ENOMEM; | ||
103 | |||
104 | INIT_LIST_HEAD(&signal_queue_head); | ||
105 | tasklet_enable(&tipc_tasklet); | ||
106 | handler_enabled = 1; | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | void handler_stop(void) | ||
111 | { | ||
112 | struct list_head *l, *n; | ||
113 | struct queue_item *item; | ||
114 | |||
115 | if (!handler_enabled) | ||
116 | return; | ||
117 | |||
118 | handler_enabled = 0; | ||
119 | tasklet_disable(&tipc_tasklet); | ||
120 | tasklet_kill(&tipc_tasklet); | ||
121 | |||
122 | spin_lock_bh(&qitem_lock); | ||
123 | list_for_each_safe(l, n, &signal_queue_head) { | ||
124 | item = list_entry(l, struct queue_item, next_signal); | ||
125 | list_del(&item->next_signal); | ||
126 | kmem_cache_free(tipc_queue_item_cache, item); | ||
127 | } | ||
128 | spin_unlock_bh(&qitem_lock); | ||
129 | |||
130 | kmem_cache_destroy(tipc_queue_item_cache); | ||
131 | } | ||
132 | |||
diff --git a/net/tipc/link.c b/net/tipc/link.c new file mode 100644 index 000000000000..7265f4be4766 --- /dev/null +++ b/net/tipc/link.c | |||
@@ -0,0 +1,3167 @@ | |||
1 | /* | ||
2 | * net/tipc/link.c: TIPC link code | ||
3 | * | ||
4 | * Copyright (c) 1996-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "dbg.h" | ||
39 | #include "link.h" | ||
40 | #include "net.h" | ||
41 | #include "node.h" | ||
42 | #include "port.h" | ||
43 | #include "addr.h" | ||
44 | #include "node_subscr.h" | ||
45 | #include "name_distr.h" | ||
46 | #include "bearer.h" | ||
47 | #include "name_table.h" | ||
48 | #include "discover.h" | ||
49 | #include "config.h" | ||
50 | #include "bcast.h" | ||
51 | |||
52 | |||
53 | /* | ||
54 | * Limit for deferred reception queue: | ||
55 | */ | ||
56 | |||
57 | #define DEF_QUEUE_LIMIT 256u | ||
58 | |||
59 | /* | ||
60 | * Link state events: | ||
61 | */ | ||
62 | |||
63 | #define STARTING_EVT 856384768 /* link processing trigger */ | ||
64 | #define TRAFFIC_MSG_EVT 560815u /* rx'd ??? */ | ||
65 | #define TIMEOUT_EVT 560817u /* link timer expired */ | ||
66 | |||
67 | /* | ||
68 | * The following two 'message types' is really just implementation | ||
69 | * data conveniently stored in the message header. | ||
70 | * They must not be considered part of the protocol | ||
71 | */ | ||
72 | #define OPEN_MSG 0 | ||
73 | #define CLOSED_MSG 1 | ||
74 | |||
75 | /* | ||
76 | * State value stored in 'exp_msg_count' | ||
77 | */ | ||
78 | |||
79 | #define START_CHANGEOVER 100000u | ||
80 | |||
81 | /** | ||
82 | * struct link_name - deconstructed link name | ||
83 | * @addr_local: network address of node at this end | ||
84 | * @if_local: name of interface at this end | ||
85 | * @addr_peer: network address of node at far end | ||
86 | * @if_peer: name of interface at far end | ||
87 | */ | ||
88 | |||
89 | struct link_name { | ||
90 | u32 addr_local; | ||
91 | char if_local[TIPC_MAX_IF_NAME]; | ||
92 | u32 addr_peer; | ||
93 | char if_peer[TIPC_MAX_IF_NAME]; | ||
94 | }; | ||
95 | |||
96 | #if 0 | ||
97 | |||
98 | /* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */ | ||
99 | |||
100 | /** | ||
101 | * struct link_event - link up/down event notification | ||
102 | */ | ||
103 | |||
104 | struct link_event { | ||
105 | u32 addr; | ||
106 | int up; | ||
107 | void (*fcn)(u32, char *, int); | ||
108 | char name[TIPC_MAX_LINK_NAME]; | ||
109 | }; | ||
110 | |||
111 | #endif | ||
112 | |||
113 | static void link_handle_out_of_seq_msg(struct link *l_ptr, | ||
114 | struct sk_buff *buf); | ||
115 | static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf); | ||
116 | static int link_recv_changeover_msg(struct link **l_ptr, struct sk_buff **buf); | ||
117 | static void link_set_supervision_props(struct link *l_ptr, u32 tolerance); | ||
118 | static int link_send_sections_long(struct port *sender, | ||
119 | struct iovec const *msg_sect, | ||
120 | u32 num_sect, u32 destnode); | ||
121 | static void link_check_defragm_bufs(struct link *l_ptr); | ||
122 | static void link_state_event(struct link *l_ptr, u32 event); | ||
123 | static void link_reset_statistics(struct link *l_ptr); | ||
124 | static void link_print(struct link *l_ptr, struct print_buf *buf, | ||
125 | const char *str); | ||
126 | |||
127 | /* | ||
128 | * Debugging code used by link routines only | ||
129 | * | ||
130 | * When debugging link problems on a system that has multiple links, | ||
131 | * the standard TIPC debugging routines may not be useful since they | ||
132 | * allow the output from multiple links to be intermixed. For this reason | ||
133 | * routines of the form "dbg_link_XXX()" have been created that will capture | ||
134 | * debug info into a link's personal print buffer, which can then be dumped | ||
135 | * into the TIPC system log (LOG) upon request. | ||
136 | * | ||
137 | * To enable per-link debugging, use LINK_LOG_BUF_SIZE to specify the size | ||
138 | * of the print buffer used by each link. If LINK_LOG_BUF_SIZE is set to 0, | ||
139 | * the dbg_link_XXX() routines simply send their output to the standard | ||
140 | * debug print buffer (DBG_OUTPUT), if it has been defined; this can be useful | ||
141 | * when there is only a single link in the system being debugged. | ||
142 | * | ||
143 | * Notes: | ||
144 | * - When enabled, LINK_LOG_BUF_SIZE should be set to at least 1000 (bytes) | ||
145 | * - "l_ptr" must be valid when using dbg_link_XXX() macros | ||
146 | */ | ||
147 | |||
148 | #define LINK_LOG_BUF_SIZE 0 | ||
149 | |||
150 | #define dbg_link(fmt, arg...) do {if (LINK_LOG_BUF_SIZE) tipc_printf(&l_ptr->print_buf, fmt, ## arg); } while(0) | ||
151 | #define dbg_link_msg(msg, txt) do {if (LINK_LOG_BUF_SIZE) msg_print(&l_ptr->print_buf, msg, txt); } while(0) | ||
152 | #define dbg_link_state(txt) do {if (LINK_LOG_BUF_SIZE) link_print(l_ptr, &l_ptr->print_buf, txt); } while(0) | ||
153 | #define dbg_link_dump() do { \ | ||
154 | if (LINK_LOG_BUF_SIZE) { \ | ||
155 | tipc_printf(LOG, "\n\nDumping link <%s>:\n", l_ptr->name); \ | ||
156 | printbuf_move(LOG, &l_ptr->print_buf); \ | ||
157 | } \ | ||
158 | } while (0) | ||
159 | |||
160 | static inline void dbg_print_link(struct link *l_ptr, const char *str) | ||
161 | { | ||
162 | if (DBG_OUTPUT) | ||
163 | link_print(l_ptr, DBG_OUTPUT, str); | ||
164 | } | ||
165 | |||
166 | static inline void dbg_print_buf_chain(struct sk_buff *root_buf) | ||
167 | { | ||
168 | if (DBG_OUTPUT) { | ||
169 | struct sk_buff *buf = root_buf; | ||
170 | |||
171 | while (buf) { | ||
172 | msg_dbg(buf_msg(buf), "In chain: "); | ||
173 | buf = buf->next; | ||
174 | } | ||
175 | } | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * Simple inlined link routines | ||
180 | */ | ||
181 | |||
182 | static inline unsigned int align(unsigned int i) | ||
183 | { | ||
184 | return (i + 3) & ~3u; | ||
185 | } | ||
186 | |||
187 | static inline int link_working_working(struct link *l_ptr) | ||
188 | { | ||
189 | return (l_ptr->state == WORKING_WORKING); | ||
190 | } | ||
191 | |||
192 | static inline int link_working_unknown(struct link *l_ptr) | ||
193 | { | ||
194 | return (l_ptr->state == WORKING_UNKNOWN); | ||
195 | } | ||
196 | |||
197 | static inline int link_reset_unknown(struct link *l_ptr) | ||
198 | { | ||
199 | return (l_ptr->state == RESET_UNKNOWN); | ||
200 | } | ||
201 | |||
202 | static inline int link_reset_reset(struct link *l_ptr) | ||
203 | { | ||
204 | return (l_ptr->state == RESET_RESET); | ||
205 | } | ||
206 | |||
207 | static inline int link_blocked(struct link *l_ptr) | ||
208 | { | ||
209 | return (l_ptr->exp_msg_count || l_ptr->blocked); | ||
210 | } | ||
211 | |||
212 | static inline int link_congested(struct link *l_ptr) | ||
213 | { | ||
214 | return (l_ptr->out_queue_size >= l_ptr->queue_limit[0]); | ||
215 | } | ||
216 | |||
217 | static inline u32 link_max_pkt(struct link *l_ptr) | ||
218 | { | ||
219 | return l_ptr->max_pkt; | ||
220 | } | ||
221 | |||
222 | static inline void link_init_max_pkt(struct link *l_ptr) | ||
223 | { | ||
224 | u32 max_pkt; | ||
225 | |||
226 | max_pkt = (l_ptr->b_ptr->publ.mtu & ~3); | ||
227 | if (max_pkt > MAX_MSG_SIZE) | ||
228 | max_pkt = MAX_MSG_SIZE; | ||
229 | |||
230 | l_ptr->max_pkt_target = max_pkt; | ||
231 | if (l_ptr->max_pkt_target < MAX_PKT_DEFAULT) | ||
232 | l_ptr->max_pkt = l_ptr->max_pkt_target; | ||
233 | else | ||
234 | l_ptr->max_pkt = MAX_PKT_DEFAULT; | ||
235 | |||
236 | l_ptr->max_pkt_probes = 0; | ||
237 | } | ||
238 | |||
239 | static inline u32 link_next_sent(struct link *l_ptr) | ||
240 | { | ||
241 | if (l_ptr->next_out) | ||
242 | return msg_seqno(buf_msg(l_ptr->next_out)); | ||
243 | return mod(l_ptr->next_out_no); | ||
244 | } | ||
245 | |||
246 | static inline u32 link_last_sent(struct link *l_ptr) | ||
247 | { | ||
248 | return mod(link_next_sent(l_ptr) - 1); | ||
249 | } | ||
250 | |||
251 | /* | ||
252 | * Simple non-inlined link routines (i.e. referenced outside this file) | ||
253 | */ | ||
254 | |||
255 | int link_is_up(struct link *l_ptr) | ||
256 | { | ||
257 | if (!l_ptr) | ||
258 | return 0; | ||
259 | return (link_working_working(l_ptr) || link_working_unknown(l_ptr)); | ||
260 | } | ||
261 | |||
262 | int link_is_active(struct link *l_ptr) | ||
263 | { | ||
264 | return ((l_ptr->owner->active_links[0] == l_ptr) || | ||
265 | (l_ptr->owner->active_links[1] == l_ptr)); | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * link_name_validate - validate & (optionally) deconstruct link name | ||
270 | * @name - ptr to link name string | ||
271 | * @name_parts - ptr to area for link name components (or NULL if not needed) | ||
272 | * | ||
273 | * Returns 1 if link name is valid, otherwise 0. | ||
274 | */ | ||
275 | |||
276 | static int link_name_validate(const char *name, struct link_name *name_parts) | ||
277 | { | ||
278 | char name_copy[TIPC_MAX_LINK_NAME]; | ||
279 | char *addr_local; | ||
280 | char *if_local; | ||
281 | char *addr_peer; | ||
282 | char *if_peer; | ||
283 | char dummy; | ||
284 | u32 z_local, c_local, n_local; | ||
285 | u32 z_peer, c_peer, n_peer; | ||
286 | u32 if_local_len; | ||
287 | u32 if_peer_len; | ||
288 | |||
289 | /* copy link name & ensure length is OK */ | ||
290 | |||
291 | name_copy[TIPC_MAX_LINK_NAME - 1] = 0; | ||
292 | /* need above in case non-Posix strncpy() doesn't pad with nulls */ | ||
293 | strncpy(name_copy, name, TIPC_MAX_LINK_NAME); | ||
294 | if (name_copy[TIPC_MAX_LINK_NAME - 1] != 0) | ||
295 | return 0; | ||
296 | |||
297 | /* ensure all component parts of link name are present */ | ||
298 | |||
299 | addr_local = name_copy; | ||
300 | if ((if_local = strchr(addr_local, ':')) == NULL) | ||
301 | return 0; | ||
302 | *(if_local++) = 0; | ||
303 | if ((addr_peer = strchr(if_local, '-')) == NULL) | ||
304 | return 0; | ||
305 | *(addr_peer++) = 0; | ||
306 | if_local_len = addr_peer - if_local; | ||
307 | if ((if_peer = strchr(addr_peer, ':')) == NULL) | ||
308 | return 0; | ||
309 | *(if_peer++) = 0; | ||
310 | if_peer_len = strlen(if_peer) + 1; | ||
311 | |||
312 | /* validate component parts of link name */ | ||
313 | |||
314 | if ((sscanf(addr_local, "%u.%u.%u%c", | ||
315 | &z_local, &c_local, &n_local, &dummy) != 3) || | ||
316 | (sscanf(addr_peer, "%u.%u.%u%c", | ||
317 | &z_peer, &c_peer, &n_peer, &dummy) != 3) || | ||
318 | (z_local > 255) || (c_local > 4095) || (n_local > 4095) || | ||
319 | (z_peer > 255) || (c_peer > 4095) || (n_peer > 4095) || | ||
320 | (if_local_len <= 1) || (if_local_len > TIPC_MAX_IF_NAME) || | ||
321 | (if_peer_len <= 1) || (if_peer_len > TIPC_MAX_IF_NAME) || | ||
322 | (strspn(if_local, tipc_alphabet) != (if_local_len - 1)) || | ||
323 | (strspn(if_peer, tipc_alphabet) != (if_peer_len - 1))) | ||
324 | return 0; | ||
325 | |||
326 | /* return link name components, if necessary */ | ||
327 | |||
328 | if (name_parts) { | ||
329 | name_parts->addr_local = tipc_addr(z_local, c_local, n_local); | ||
330 | strcpy(name_parts->if_local, if_local); | ||
331 | name_parts->addr_peer = tipc_addr(z_peer, c_peer, n_peer); | ||
332 | strcpy(name_parts->if_peer, if_peer); | ||
333 | } | ||
334 | return 1; | ||
335 | } | ||
336 | |||
337 | /** | ||
338 | * link_timeout - handle expiration of link timer | ||
339 | * @l_ptr: pointer to link | ||
340 | * | ||
341 | * This routine must not grab "net_lock" to avoid a potential deadlock conflict | ||
342 | * with link_delete(). (There is no risk that the node will be deleted by | ||
343 | * another thread because link_delete() always cancels the link timer before | ||
344 | * node_delete() is called.) | ||
345 | */ | ||
346 | |||
347 | static void link_timeout(struct link *l_ptr) | ||
348 | { | ||
349 | node_lock(l_ptr->owner); | ||
350 | |||
351 | /* update counters used in statistical profiling of send traffic */ | ||
352 | |||
353 | l_ptr->stats.accu_queue_sz += l_ptr->out_queue_size; | ||
354 | l_ptr->stats.queue_sz_counts++; | ||
355 | |||
356 | if (l_ptr->out_queue_size > l_ptr->stats.max_queue_sz) | ||
357 | l_ptr->stats.max_queue_sz = l_ptr->out_queue_size; | ||
358 | |||
359 | if (l_ptr->first_out) { | ||
360 | struct tipc_msg *msg = buf_msg(l_ptr->first_out); | ||
361 | u32 length = msg_size(msg); | ||
362 | |||
363 | if ((msg_user(msg) == MSG_FRAGMENTER) | ||
364 | && (msg_type(msg) == FIRST_FRAGMENT)) { | ||
365 | length = msg_size(msg_get_wrapped(msg)); | ||
366 | } | ||
367 | if (length) { | ||
368 | l_ptr->stats.msg_lengths_total += length; | ||
369 | l_ptr->stats.msg_length_counts++; | ||
370 | if (length <= 64) | ||
371 | l_ptr->stats.msg_length_profile[0]++; | ||
372 | else if (length <= 256) | ||
373 | l_ptr->stats.msg_length_profile[1]++; | ||
374 | else if (length <= 1024) | ||
375 | l_ptr->stats.msg_length_profile[2]++; | ||
376 | else if (length <= 4096) | ||
377 | l_ptr->stats.msg_length_profile[3]++; | ||
378 | else if (length <= 16384) | ||
379 | l_ptr->stats.msg_length_profile[4]++; | ||
380 | else if (length <= 32768) | ||
381 | l_ptr->stats.msg_length_profile[5]++; | ||
382 | else | ||
383 | l_ptr->stats.msg_length_profile[6]++; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | /* do all other link processing performed on a periodic basis */ | ||
388 | |||
389 | link_check_defragm_bufs(l_ptr); | ||
390 | |||
391 | link_state_event(l_ptr, TIMEOUT_EVT); | ||
392 | |||
393 | if (l_ptr->next_out) | ||
394 | link_push_queue(l_ptr); | ||
395 | |||
396 | node_unlock(l_ptr->owner); | ||
397 | } | ||
398 | |||
399 | static inline void link_set_timer(struct link *l_ptr, u32 time) | ||
400 | { | ||
401 | k_start_timer(&l_ptr->timer, time); | ||
402 | } | ||
403 | |||
404 | /** | ||
405 | * link_create - create a new link | ||
406 | * @b_ptr: pointer to associated bearer | ||
407 | * @peer: network address of node at other end of link | ||
408 | * @media_addr: media address to use when sending messages over link | ||
409 | * | ||
410 | * Returns pointer to link. | ||
411 | */ | ||
412 | |||
413 | struct link *link_create(struct bearer *b_ptr, const u32 peer, | ||
414 | const struct tipc_media_addr *media_addr) | ||
415 | { | ||
416 | struct link *l_ptr; | ||
417 | struct tipc_msg *msg; | ||
418 | char *if_name; | ||
419 | |||
420 | l_ptr = (struct link *)kmalloc(sizeof(*l_ptr), GFP_ATOMIC); | ||
421 | if (!l_ptr) { | ||
422 | warn("Memory squeeze; Failed to create link\n"); | ||
423 | return NULL; | ||
424 | } | ||
425 | memset(l_ptr, 0, sizeof(*l_ptr)); | ||
426 | |||
427 | l_ptr->addr = peer; | ||
428 | if_name = strchr(b_ptr->publ.name, ':') + 1; | ||
429 | sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:", | ||
430 | tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), | ||
431 | tipc_node(tipc_own_addr), | ||
432 | if_name, | ||
433 | tipc_zone(peer), tipc_cluster(peer), tipc_node(peer)); | ||
434 | /* note: peer i/f is appended to link name by reset/activate */ | ||
435 | memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr)); | ||
436 | k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr); | ||
437 | list_add_tail(&l_ptr->link_list, &b_ptr->links); | ||
438 | l_ptr->checkpoint = 1; | ||
439 | l_ptr->b_ptr = b_ptr; | ||
440 | link_set_supervision_props(l_ptr, b_ptr->media->tolerance); | ||
441 | l_ptr->state = RESET_UNKNOWN; | ||
442 | |||
443 | l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg; | ||
444 | msg = l_ptr->pmsg; | ||
445 | msg_init(msg, LINK_PROTOCOL, RESET_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); | ||
446 | msg_set_size(msg, sizeof(l_ptr->proto_msg)); | ||
447 | msg_set_session(msg, tipc_random); | ||
448 | msg_set_bearer_id(msg, b_ptr->identity); | ||
449 | strcpy((char *)msg_data(msg), if_name); | ||
450 | |||
451 | l_ptr->priority = b_ptr->priority; | ||
452 | link_set_queue_limits(l_ptr, b_ptr->media->window); | ||
453 | |||
454 | link_init_max_pkt(l_ptr); | ||
455 | |||
456 | l_ptr->next_out_no = 1; | ||
457 | INIT_LIST_HEAD(&l_ptr->waiting_ports); | ||
458 | |||
459 | link_reset_statistics(l_ptr); | ||
460 | |||
461 | l_ptr->owner = node_attach_link(l_ptr); | ||
462 | if (!l_ptr->owner) { | ||
463 | kfree(l_ptr); | ||
464 | return NULL; | ||
465 | } | ||
466 | |||
467 | if (LINK_LOG_BUF_SIZE) { | ||
468 | char *pb = kmalloc(LINK_LOG_BUF_SIZE, GFP_ATOMIC); | ||
469 | |||
470 | if (!pb) { | ||
471 | kfree(l_ptr); | ||
472 | warn("Memory squeeze; Failed to create link\n"); | ||
473 | return NULL; | ||
474 | } | ||
475 | printbuf_init(&l_ptr->print_buf, pb, LINK_LOG_BUF_SIZE); | ||
476 | } | ||
477 | |||
478 | k_signal((Handler)link_start, (unsigned long)l_ptr); | ||
479 | |||
480 | dbg("link_create(): tolerance = %u,cont intv = %u, abort_limit = %u\n", | ||
481 | l_ptr->tolerance, l_ptr->continuity_interval, l_ptr->abort_limit); | ||
482 | |||
483 | return l_ptr; | ||
484 | } | ||
485 | |||
486 | /** | ||
487 | * link_delete - delete a link | ||
488 | * @l_ptr: pointer to link | ||
489 | * | ||
490 | * Note: 'net_lock' is write_locked, bearer is locked. | ||
491 | * This routine must not grab the node lock until after link timer cancellation | ||
492 | * to avoid a potential deadlock situation. | ||
493 | */ | ||
494 | |||
495 | void link_delete(struct link *l_ptr) | ||
496 | { | ||
497 | if (!l_ptr) { | ||
498 | err("Attempt to delete non-existent link\n"); | ||
499 | return; | ||
500 | } | ||
501 | |||
502 | dbg("link_delete()\n"); | ||
503 | |||
504 | k_cancel_timer(&l_ptr->timer); | ||
505 | |||
506 | node_lock(l_ptr->owner); | ||
507 | link_reset(l_ptr); | ||
508 | node_detach_link(l_ptr->owner, l_ptr); | ||
509 | link_stop(l_ptr); | ||
510 | list_del_init(&l_ptr->link_list); | ||
511 | if (LINK_LOG_BUF_SIZE) | ||
512 | kfree(l_ptr->print_buf.buf); | ||
513 | node_unlock(l_ptr->owner); | ||
514 | k_term_timer(&l_ptr->timer); | ||
515 | kfree(l_ptr); | ||
516 | } | ||
517 | |||
518 | void link_start(struct link *l_ptr) | ||
519 | { | ||
520 | dbg("link_start %x\n", l_ptr); | ||
521 | link_state_event(l_ptr, STARTING_EVT); | ||
522 | } | ||
523 | |||
524 | /** | ||
525 | * link_schedule_port - schedule port for deferred sending | ||
526 | * @l_ptr: pointer to link | ||
527 | * @origport: reference to sending port | ||
528 | * @sz: amount of data to be sent | ||
529 | * | ||
530 | * Schedules port for renewed sending of messages after link congestion | ||
531 | * has abated. | ||
532 | */ | ||
533 | |||
534 | static int link_schedule_port(struct link *l_ptr, u32 origport, u32 sz) | ||
535 | { | ||
536 | struct port *p_ptr; | ||
537 | |||
538 | spin_lock_bh(&port_list_lock); | ||
539 | p_ptr = port_lock(origport); | ||
540 | if (p_ptr) { | ||
541 | if (!p_ptr->wakeup) | ||
542 | goto exit; | ||
543 | if (!list_empty(&p_ptr->wait_list)) | ||
544 | goto exit; | ||
545 | p_ptr->congested_link = l_ptr; | ||
546 | p_ptr->publ.congested = 1; | ||
547 | p_ptr->waiting_pkts = 1 + ((sz - 1) / link_max_pkt(l_ptr)); | ||
548 | list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports); | ||
549 | l_ptr->stats.link_congs++; | ||
550 | exit: | ||
551 | port_unlock(p_ptr); | ||
552 | } | ||
553 | spin_unlock_bh(&port_list_lock); | ||
554 | return -ELINKCONG; | ||
555 | } | ||
556 | |||
557 | void link_wakeup_ports(struct link *l_ptr, int all) | ||
558 | { | ||
559 | struct port *p_ptr; | ||
560 | struct port *temp_p_ptr; | ||
561 | int win = l_ptr->queue_limit[0] - l_ptr->out_queue_size; | ||
562 | |||
563 | if (all) | ||
564 | win = 100000; | ||
565 | if (win <= 0) | ||
566 | return; | ||
567 | if (!spin_trylock_bh(&port_list_lock)) | ||
568 | return; | ||
569 | if (link_congested(l_ptr)) | ||
570 | goto exit; | ||
571 | list_for_each_entry_safe(p_ptr, temp_p_ptr, &l_ptr->waiting_ports, | ||
572 | wait_list) { | ||
573 | if (win <= 0) | ||
574 | break; | ||
575 | list_del_init(&p_ptr->wait_list); | ||
576 | p_ptr->congested_link = 0; | ||
577 | assert(p_ptr->wakeup); | ||
578 | spin_lock_bh(p_ptr->publ.lock); | ||
579 | p_ptr->publ.congested = 0; | ||
580 | p_ptr->wakeup(&p_ptr->publ); | ||
581 | win -= p_ptr->waiting_pkts; | ||
582 | spin_unlock_bh(p_ptr->publ.lock); | ||
583 | } | ||
584 | |||
585 | exit: | ||
586 | spin_unlock_bh(&port_list_lock); | ||
587 | } | ||
588 | |||
589 | /** | ||
590 | * link_release_outqueue - purge link's outbound message queue | ||
591 | * @l_ptr: pointer to link | ||
592 | */ | ||
593 | |||
594 | static void link_release_outqueue(struct link *l_ptr) | ||
595 | { | ||
596 | struct sk_buff *buf = l_ptr->first_out; | ||
597 | struct sk_buff *next; | ||
598 | |||
599 | while (buf) { | ||
600 | next = buf->next; | ||
601 | buf_discard(buf); | ||
602 | buf = next; | ||
603 | } | ||
604 | l_ptr->first_out = NULL; | ||
605 | l_ptr->out_queue_size = 0; | ||
606 | } | ||
607 | |||
608 | /** | ||
609 | * link_reset_fragments - purge link's inbound message fragments queue | ||
610 | * @l_ptr: pointer to link | ||
611 | */ | ||
612 | |||
613 | void link_reset_fragments(struct link *l_ptr) | ||
614 | { | ||
615 | struct sk_buff *buf = l_ptr->defragm_buf; | ||
616 | struct sk_buff *next; | ||
617 | |||
618 | while (buf) { | ||
619 | next = buf->next; | ||
620 | buf_discard(buf); | ||
621 | buf = next; | ||
622 | } | ||
623 | l_ptr->defragm_buf = NULL; | ||
624 | } | ||
625 | |||
626 | /** | ||
627 | * link_stop - purge all inbound and outbound messages associated with link | ||
628 | * @l_ptr: pointer to link | ||
629 | */ | ||
630 | |||
631 | void link_stop(struct link *l_ptr) | ||
632 | { | ||
633 | struct sk_buff *buf; | ||
634 | struct sk_buff *next; | ||
635 | |||
636 | buf = l_ptr->oldest_deferred_in; | ||
637 | while (buf) { | ||
638 | next = buf->next; | ||
639 | buf_discard(buf); | ||
640 | buf = next; | ||
641 | } | ||
642 | |||
643 | buf = l_ptr->first_out; | ||
644 | while (buf) { | ||
645 | next = buf->next; | ||
646 | buf_discard(buf); | ||
647 | buf = next; | ||
648 | } | ||
649 | |||
650 | link_reset_fragments(l_ptr); | ||
651 | |||
652 | buf_discard(l_ptr->proto_msg_queue); | ||
653 | l_ptr->proto_msg_queue = NULL; | ||
654 | } | ||
655 | |||
656 | #if 0 | ||
657 | |||
658 | /* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */ | ||
659 | |||
660 | static void link_recv_event(struct link_event *ev) | ||
661 | { | ||
662 | ev->fcn(ev->addr, ev->name, ev->up); | ||
663 | kfree(ev); | ||
664 | } | ||
665 | |||
666 | static void link_send_event(void (*fcn)(u32 a, char *n, int up), | ||
667 | struct link *l_ptr, int up) | ||
668 | { | ||
669 | struct link_event *ev; | ||
670 | |||
671 | ev = kmalloc(sizeof(*ev), GFP_ATOMIC); | ||
672 | if (!ev) { | ||
673 | warn("Link event allocation failure\n"); | ||
674 | return; | ||
675 | } | ||
676 | ev->addr = l_ptr->addr; | ||
677 | ev->up = up; | ||
678 | ev->fcn = fcn; | ||
679 | memcpy(ev->name, l_ptr->name, TIPC_MAX_LINK_NAME); | ||
680 | k_signal((Handler)link_recv_event, (unsigned long)ev); | ||
681 | } | ||
682 | |||
683 | #else | ||
684 | |||
685 | #define link_send_event(fcn, l_ptr, up) do { } while (0) | ||
686 | |||
687 | #endif | ||
688 | |||
689 | void link_reset(struct link *l_ptr) | ||
690 | { | ||
691 | struct sk_buff *buf; | ||
692 | u32 prev_state = l_ptr->state; | ||
693 | u32 checkpoint = l_ptr->next_in_no; | ||
694 | |||
695 | msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1); | ||
696 | |||
697 | /* Link is down, accept any session: */ | ||
698 | l_ptr->peer_session = 0; | ||
699 | |||
700 | /* Prepare for max packet size negotiation */ | ||
701 | link_init_max_pkt(l_ptr); | ||
702 | |||
703 | l_ptr->state = RESET_UNKNOWN; | ||
704 | dbg_link_state("Resetting Link\n"); | ||
705 | |||
706 | if ((prev_state == RESET_UNKNOWN) || (prev_state == RESET_RESET)) | ||
707 | return; | ||
708 | |||
709 | node_link_down(l_ptr->owner, l_ptr); | ||
710 | bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr); | ||
711 | #if 0 | ||
712 | tipc_printf(CONS, "\nReset link <%s>\n", l_ptr->name); | ||
713 | dbg_link_dump(); | ||
714 | #endif | ||
715 | if (node_has_active_links(l_ptr->owner) && | ||
716 | l_ptr->owner->permit_changeover) { | ||
717 | l_ptr->reset_checkpoint = checkpoint; | ||
718 | l_ptr->exp_msg_count = START_CHANGEOVER; | ||
719 | } | ||
720 | |||
721 | /* Clean up all queues: */ | ||
722 | |||
723 | link_release_outqueue(l_ptr); | ||
724 | buf_discard(l_ptr->proto_msg_queue); | ||
725 | l_ptr->proto_msg_queue = NULL; | ||
726 | buf = l_ptr->oldest_deferred_in; | ||
727 | while (buf) { | ||
728 | struct sk_buff *next = buf->next; | ||
729 | buf_discard(buf); | ||
730 | buf = next; | ||
731 | } | ||
732 | if (!list_empty(&l_ptr->waiting_ports)) | ||
733 | link_wakeup_ports(l_ptr, 1); | ||
734 | |||
735 | l_ptr->retransm_queue_head = 0; | ||
736 | l_ptr->retransm_queue_size = 0; | ||
737 | l_ptr->last_out = NULL; | ||
738 | l_ptr->first_out = NULL; | ||
739 | l_ptr->next_out = NULL; | ||
740 | l_ptr->unacked_window = 0; | ||
741 | l_ptr->checkpoint = 1; | ||
742 | l_ptr->next_out_no = 1; | ||
743 | l_ptr->deferred_inqueue_sz = 0; | ||
744 | l_ptr->oldest_deferred_in = NULL; | ||
745 | l_ptr->newest_deferred_in = NULL; | ||
746 | l_ptr->fsm_msg_cnt = 0; | ||
747 | l_ptr->stale_count = 0; | ||
748 | link_reset_statistics(l_ptr); | ||
749 | |||
750 | link_send_event(cfg_link_event, l_ptr, 0); | ||
751 | if (!in_own_cluster(l_ptr->addr)) | ||
752 | link_send_event(disc_link_event, l_ptr, 0); | ||
753 | } | ||
754 | |||
755 | |||
756 | static void link_activate(struct link *l_ptr) | ||
757 | { | ||
758 | l_ptr->next_in_no = 1; | ||
759 | node_link_up(l_ptr->owner, l_ptr); | ||
760 | bearer_add_dest(l_ptr->b_ptr, l_ptr->addr); | ||
761 | link_send_event(cfg_link_event, l_ptr, 1); | ||
762 | if (!in_own_cluster(l_ptr->addr)) | ||
763 | link_send_event(disc_link_event, l_ptr, 1); | ||
764 | } | ||
765 | |||
766 | /** | ||
767 | * link_state_event - link finite state machine | ||
768 | * @l_ptr: pointer to link | ||
769 | * @event: state machine event to process | ||
770 | */ | ||
771 | |||
772 | static void link_state_event(struct link *l_ptr, unsigned event) | ||
773 | { | ||
774 | struct link *other; | ||
775 | u32 cont_intv = l_ptr->continuity_interval; | ||
776 | |||
777 | if (!l_ptr->started && (event != STARTING_EVT)) | ||
778 | return; /* Not yet. */ | ||
779 | |||
780 | if (link_blocked(l_ptr)) { | ||
781 | if (event == TIMEOUT_EVT) { | ||
782 | link_set_timer(l_ptr, cont_intv); | ||
783 | } | ||
784 | return; /* Changeover going on */ | ||
785 | } | ||
786 | dbg_link("STATE_EV: <%s> ", l_ptr->name); | ||
787 | |||
788 | switch (l_ptr->state) { | ||
789 | case WORKING_WORKING: | ||
790 | dbg_link("WW/"); | ||
791 | switch (event) { | ||
792 | case TRAFFIC_MSG_EVT: | ||
793 | dbg_link("TRF-"); | ||
794 | /* fall through */ | ||
795 | case ACTIVATE_MSG: | ||
796 | dbg_link("ACT\n"); | ||
797 | break; | ||
798 | case TIMEOUT_EVT: | ||
799 | dbg_link("TIM "); | ||
800 | if (l_ptr->next_in_no != l_ptr->checkpoint) { | ||
801 | l_ptr->checkpoint = l_ptr->next_in_no; | ||
802 | if (bclink_acks_missing(l_ptr->owner)) { | ||
803 | link_send_proto_msg(l_ptr, STATE_MSG, | ||
804 | 0, 0, 0, 0, 0); | ||
805 | l_ptr->fsm_msg_cnt++; | ||
806 | } else if (l_ptr->max_pkt < l_ptr->max_pkt_target) { | ||
807 | link_send_proto_msg(l_ptr, STATE_MSG, | ||
808 | 1, 0, 0, 0, 0); | ||
809 | l_ptr->fsm_msg_cnt++; | ||
810 | } | ||
811 | link_set_timer(l_ptr, cont_intv); | ||
812 | break; | ||
813 | } | ||
814 | dbg_link(" -> WU\n"); | ||
815 | l_ptr->state = WORKING_UNKNOWN; | ||
816 | l_ptr->fsm_msg_cnt = 0; | ||
817 | link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); | ||
818 | l_ptr->fsm_msg_cnt++; | ||
819 | link_set_timer(l_ptr, cont_intv / 4); | ||
820 | break; | ||
821 | case RESET_MSG: | ||
822 | dbg_link("RES -> RR\n"); | ||
823 | link_reset(l_ptr); | ||
824 | l_ptr->state = RESET_RESET; | ||
825 | l_ptr->fsm_msg_cnt = 0; | ||
826 | link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); | ||
827 | l_ptr->fsm_msg_cnt++; | ||
828 | link_set_timer(l_ptr, cont_intv); | ||
829 | break; | ||
830 | default: | ||
831 | err("Unknown link event %u in WW state\n", event); | ||
832 | } | ||
833 | break; | ||
834 | case WORKING_UNKNOWN: | ||
835 | dbg_link("WU/"); | ||
836 | switch (event) { | ||
837 | case TRAFFIC_MSG_EVT: | ||
838 | dbg_link("TRF-"); | ||
839 | case ACTIVATE_MSG: | ||
840 | dbg_link("ACT -> WW\n"); | ||
841 | l_ptr->state = WORKING_WORKING; | ||
842 | l_ptr->fsm_msg_cnt = 0; | ||
843 | link_set_timer(l_ptr, cont_intv); | ||
844 | break; | ||
845 | case RESET_MSG: | ||
846 | dbg_link("RES -> RR\n"); | ||
847 | link_reset(l_ptr); | ||
848 | l_ptr->state = RESET_RESET; | ||
849 | l_ptr->fsm_msg_cnt = 0; | ||
850 | link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); | ||
851 | l_ptr->fsm_msg_cnt++; | ||
852 | link_set_timer(l_ptr, cont_intv); | ||
853 | break; | ||
854 | case TIMEOUT_EVT: | ||
855 | dbg_link("TIM "); | ||
856 | if (l_ptr->next_in_no != l_ptr->checkpoint) { | ||
857 | dbg_link("-> WW \n"); | ||
858 | l_ptr->state = WORKING_WORKING; | ||
859 | l_ptr->fsm_msg_cnt = 0; | ||
860 | l_ptr->checkpoint = l_ptr->next_in_no; | ||
861 | if (bclink_acks_missing(l_ptr->owner)) { | ||
862 | link_send_proto_msg(l_ptr, STATE_MSG, | ||
863 | 0, 0, 0, 0, 0); | ||
864 | l_ptr->fsm_msg_cnt++; | ||
865 | } | ||
866 | link_set_timer(l_ptr, cont_intv); | ||
867 | } else if (l_ptr->fsm_msg_cnt < l_ptr->abort_limit) { | ||
868 | dbg_link("Probing %u/%u,timer = %u ms)\n", | ||
869 | l_ptr->fsm_msg_cnt, l_ptr->abort_limit, | ||
870 | cont_intv / 4); | ||
871 | link_send_proto_msg(l_ptr, STATE_MSG, | ||
872 | 1, 0, 0, 0, 0); | ||
873 | l_ptr->fsm_msg_cnt++; | ||
874 | link_set_timer(l_ptr, cont_intv / 4); | ||
875 | } else { /* Link has failed */ | ||
876 | dbg_link("-> RU (%u probes unanswered)\n", | ||
877 | l_ptr->fsm_msg_cnt); | ||
878 | link_reset(l_ptr); | ||
879 | l_ptr->state = RESET_UNKNOWN; | ||
880 | l_ptr->fsm_msg_cnt = 0; | ||
881 | link_send_proto_msg(l_ptr, RESET_MSG, | ||
882 | 0, 0, 0, 0, 0); | ||
883 | l_ptr->fsm_msg_cnt++; | ||
884 | link_set_timer(l_ptr, cont_intv); | ||
885 | } | ||
886 | break; | ||
887 | default: | ||
888 | err("Unknown link event %u in WU state\n", event); | ||
889 | } | ||
890 | break; | ||
891 | case RESET_UNKNOWN: | ||
892 | dbg_link("RU/"); | ||
893 | switch (event) { | ||
894 | case TRAFFIC_MSG_EVT: | ||
895 | dbg_link("TRF-\n"); | ||
896 | break; | ||
897 | case ACTIVATE_MSG: | ||
898 | other = l_ptr->owner->active_links[0]; | ||
899 | if (other && link_working_unknown(other)) { | ||
900 | dbg_link("ACT\n"); | ||
901 | break; | ||
902 | } | ||
903 | dbg_link("ACT -> WW\n"); | ||
904 | l_ptr->state = WORKING_WORKING; | ||
905 | l_ptr->fsm_msg_cnt = 0; | ||
906 | link_activate(l_ptr); | ||
907 | link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); | ||
908 | l_ptr->fsm_msg_cnt++; | ||
909 | link_set_timer(l_ptr, cont_intv); | ||
910 | break; | ||
911 | case RESET_MSG: | ||
912 | dbg_link("RES \n"); | ||
913 | dbg_link(" -> RR\n"); | ||
914 | l_ptr->state = RESET_RESET; | ||
915 | l_ptr->fsm_msg_cnt = 0; | ||
916 | link_send_proto_msg(l_ptr, ACTIVATE_MSG, 1, 0, 0, 0, 0); | ||
917 | l_ptr->fsm_msg_cnt++; | ||
918 | link_set_timer(l_ptr, cont_intv); | ||
919 | break; | ||
920 | case STARTING_EVT: | ||
921 | dbg_link("START-"); | ||
922 | l_ptr->started = 1; | ||
923 | /* fall through */ | ||
924 | case TIMEOUT_EVT: | ||
925 | dbg_link("TIM \n"); | ||
926 | link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0); | ||
927 | l_ptr->fsm_msg_cnt++; | ||
928 | link_set_timer(l_ptr, cont_intv); | ||
929 | break; | ||
930 | default: | ||
931 | err("Unknown link event %u in RU state\n", event); | ||
932 | } | ||
933 | break; | ||
934 | case RESET_RESET: | ||
935 | dbg_link("RR/ "); | ||
936 | switch (event) { | ||
937 | case TRAFFIC_MSG_EVT: | ||
938 | dbg_link("TRF-"); | ||
939 | /* fall through */ | ||
940 | case ACTIVATE_MSG: | ||
941 | other = l_ptr->owner->active_links[0]; | ||
942 | if (other && link_working_unknown(other)) { | ||
943 | dbg_link("ACT\n"); | ||
944 | break; | ||
945 | } | ||
946 | dbg_link("ACT -> WW\n"); | ||
947 | l_ptr->state = WORKING_WORKING; | ||
948 | l_ptr->fsm_msg_cnt = 0; | ||
949 | link_activate(l_ptr); | ||
950 | link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); | ||
951 | l_ptr->fsm_msg_cnt++; | ||
952 | link_set_timer(l_ptr, cont_intv); | ||
953 | break; | ||
954 | case RESET_MSG: | ||
955 | dbg_link("RES\n"); | ||
956 | break; | ||
957 | case TIMEOUT_EVT: | ||
958 | dbg_link("TIM\n"); | ||
959 | link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); | ||
960 | l_ptr->fsm_msg_cnt++; | ||
961 | link_set_timer(l_ptr, cont_intv); | ||
962 | dbg_link("fsm_msg_cnt %u\n", l_ptr->fsm_msg_cnt); | ||
963 | break; | ||
964 | default: | ||
965 | err("Unknown link event %u in RR state\n", event); | ||
966 | } | ||
967 | break; | ||
968 | default: | ||
969 | err("Unknown link state %u/%u\n", l_ptr->state, event); | ||
970 | } | ||
971 | } | ||
972 | |||
973 | /* | ||
974 | * link_bundle_buf(): Append contents of a buffer to | ||
975 | * the tail of an existing one. | ||
976 | */ | ||
977 | |||
978 | static int link_bundle_buf(struct link *l_ptr, | ||
979 | struct sk_buff *bundler, | ||
980 | struct sk_buff *buf) | ||
981 | { | ||
982 | struct tipc_msg *bundler_msg = buf_msg(bundler); | ||
983 | struct tipc_msg *msg = buf_msg(buf); | ||
984 | u32 size = msg_size(msg); | ||
985 | u32 to_pos = align(msg_size(bundler_msg)); | ||
986 | u32 rest = link_max_pkt(l_ptr) - to_pos; | ||
987 | |||
988 | if (msg_user(bundler_msg) != MSG_BUNDLER) | ||
989 | return 0; | ||
990 | if (msg_type(bundler_msg) != OPEN_MSG) | ||
991 | return 0; | ||
992 | if (rest < align(size)) | ||
993 | return 0; | ||
994 | |||
995 | skb_put(bundler, (to_pos - msg_size(bundler_msg)) + size); | ||
996 | memcpy(bundler->data + to_pos, buf->data, size); | ||
997 | msg_set_size(bundler_msg, to_pos + size); | ||
998 | msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1); | ||
999 | dbg("Packed msg # %u(%u octets) into pos %u in buf(#%u)\n", | ||
1000 | msg_msgcnt(bundler_msg), size, to_pos, msg_seqno(bundler_msg)); | ||
1001 | msg_dbg(msg, "PACKD:"); | ||
1002 | buf_discard(buf); | ||
1003 | l_ptr->stats.sent_bundled++; | ||
1004 | return 1; | ||
1005 | } | ||
1006 | |||
1007 | static inline void link_add_to_outqueue(struct link *l_ptr, | ||
1008 | struct sk_buff *buf, | ||
1009 | struct tipc_msg *msg) | ||
1010 | { | ||
1011 | u32 ack = mod(l_ptr->next_in_no - 1); | ||
1012 | u32 seqno = mod(l_ptr->next_out_no++); | ||
1013 | |||
1014 | msg_set_word(msg, 2, ((ack << 16) | seqno)); | ||
1015 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | ||
1016 | buf->next = NULL; | ||
1017 | if (l_ptr->first_out) { | ||
1018 | l_ptr->last_out->next = buf; | ||
1019 | l_ptr->last_out = buf; | ||
1020 | } else | ||
1021 | l_ptr->first_out = l_ptr->last_out = buf; | ||
1022 | l_ptr->out_queue_size++; | ||
1023 | } | ||
1024 | |||
1025 | /* | ||
1026 | * link_send_buf() is the 'full path' for messages, called from | ||
1027 | * inside TIPC when the 'fast path' in tipc_send_buf | ||
1028 | * has failed, and from link_send() | ||
1029 | */ | ||
1030 | |||
1031 | int link_send_buf(struct link *l_ptr, struct sk_buff *buf) | ||
1032 | { | ||
1033 | struct tipc_msg *msg = buf_msg(buf); | ||
1034 | u32 size = msg_size(msg); | ||
1035 | u32 dsz = msg_data_sz(msg); | ||
1036 | u32 queue_size = l_ptr->out_queue_size; | ||
1037 | u32 imp = msg_tot_importance(msg); | ||
1038 | u32 queue_limit = l_ptr->queue_limit[imp]; | ||
1039 | u32 max_packet = link_max_pkt(l_ptr); | ||
1040 | |||
1041 | msg_set_prevnode(msg, tipc_own_addr); /* If routed message */ | ||
1042 | |||
1043 | /* Match msg importance against queue limits: */ | ||
1044 | |||
1045 | if (unlikely(queue_size >= queue_limit)) { | ||
1046 | if (imp <= TIPC_CRITICAL_IMPORTANCE) { | ||
1047 | return link_schedule_port(l_ptr, msg_origport(msg), | ||
1048 | size); | ||
1049 | } | ||
1050 | msg_dbg(msg, "TIPC: Congestion, throwing away\n"); | ||
1051 | buf_discard(buf); | ||
1052 | if (imp > CONN_MANAGER) { | ||
1053 | warn("Resetting <%s>, send queue full", l_ptr->name); | ||
1054 | link_reset(l_ptr); | ||
1055 | } | ||
1056 | return dsz; | ||
1057 | } | ||
1058 | |||
1059 | /* Fragmentation needed ? */ | ||
1060 | |||
1061 | if (size > max_packet) | ||
1062 | return link_send_long_buf(l_ptr, buf); | ||
1063 | |||
1064 | /* Packet can be queued or sent: */ | ||
1065 | |||
1066 | if (queue_size > l_ptr->stats.max_queue_sz) | ||
1067 | l_ptr->stats.max_queue_sz = queue_size; | ||
1068 | |||
1069 | if (likely(!bearer_congested(l_ptr->b_ptr, l_ptr) && | ||
1070 | !link_congested(l_ptr))) { | ||
1071 | link_add_to_outqueue(l_ptr, buf, msg); | ||
1072 | |||
1073 | if (likely(bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr))) { | ||
1074 | l_ptr->unacked_window = 0; | ||
1075 | } else { | ||
1076 | bearer_schedule(l_ptr->b_ptr, l_ptr); | ||
1077 | l_ptr->stats.bearer_congs++; | ||
1078 | l_ptr->next_out = buf; | ||
1079 | } | ||
1080 | return dsz; | ||
1081 | } | ||
1082 | /* Congestion: can message be bundled ?: */ | ||
1083 | |||
1084 | if ((msg_user(msg) != CHANGEOVER_PROTOCOL) && | ||
1085 | (msg_user(msg) != MSG_FRAGMENTER)) { | ||
1086 | |||
1087 | /* Try adding message to an existing bundle */ | ||
1088 | |||
1089 | if (l_ptr->next_out && | ||
1090 | link_bundle_buf(l_ptr, l_ptr->last_out, buf)) { | ||
1091 | bearer_resolve_congestion(l_ptr->b_ptr, l_ptr); | ||
1092 | return dsz; | ||
1093 | } | ||
1094 | |||
1095 | /* Try creating a new bundle */ | ||
1096 | |||
1097 | if (size <= max_packet * 2 / 3) { | ||
1098 | struct sk_buff *bundler = buf_acquire(max_packet); | ||
1099 | struct tipc_msg bundler_hdr; | ||
1100 | |||
1101 | if (bundler) { | ||
1102 | msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG, | ||
1103 | TIPC_OK, INT_H_SIZE, l_ptr->addr); | ||
1104 | memcpy(bundler->data, (unchar *)&bundler_hdr, | ||
1105 | INT_H_SIZE); | ||
1106 | skb_trim(bundler, INT_H_SIZE); | ||
1107 | link_bundle_buf(l_ptr, bundler, buf); | ||
1108 | buf = bundler; | ||
1109 | msg = buf_msg(buf); | ||
1110 | l_ptr->stats.sent_bundles++; | ||
1111 | } | ||
1112 | } | ||
1113 | } | ||
1114 | if (!l_ptr->next_out) | ||
1115 | l_ptr->next_out = buf; | ||
1116 | link_add_to_outqueue(l_ptr, buf, msg); | ||
1117 | bearer_resolve_congestion(l_ptr->b_ptr, l_ptr); | ||
1118 | return dsz; | ||
1119 | } | ||
1120 | |||
1121 | /* | ||
1122 | * link_send(): same as link_send_buf(), but the link to use has | ||
1123 | * not been selected yet, and the the owner node is not locked | ||
1124 | * Called by TIPC internal users, e.g. the name distributor | ||
1125 | */ | ||
1126 | |||
1127 | int link_send(struct sk_buff *buf, u32 dest, u32 selector) | ||
1128 | { | ||
1129 | struct link *l_ptr; | ||
1130 | struct node *n_ptr; | ||
1131 | int res = -ELINKCONG; | ||
1132 | |||
1133 | read_lock_bh(&net_lock); | ||
1134 | n_ptr = node_select(dest, selector); | ||
1135 | if (n_ptr) { | ||
1136 | node_lock(n_ptr); | ||
1137 | l_ptr = n_ptr->active_links[selector & 1]; | ||
1138 | dbg("link_send: found link %x for dest %x\n", l_ptr, dest); | ||
1139 | if (l_ptr) { | ||
1140 | res = link_send_buf(l_ptr, buf); | ||
1141 | } | ||
1142 | node_unlock(n_ptr); | ||
1143 | } else { | ||
1144 | dbg("Attempt to send msg to unknown node:\n"); | ||
1145 | msg_dbg(buf_msg(buf),">>>"); | ||
1146 | buf_discard(buf); | ||
1147 | } | ||
1148 | read_unlock_bh(&net_lock); | ||
1149 | return res; | ||
1150 | } | ||
1151 | |||
1152 | /* | ||
1153 | * link_send_buf_fast: Entry for data messages where the | ||
1154 | * destination link is known and the header is complete, | ||
1155 | * inclusive total message length. Very time critical. | ||
1156 | * Link is locked. Returns user data length. | ||
1157 | */ | ||
1158 | |||
1159 | static inline int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf, | ||
1160 | u32 *used_max_pkt) | ||
1161 | { | ||
1162 | struct tipc_msg *msg = buf_msg(buf); | ||
1163 | int res = msg_data_sz(msg); | ||
1164 | |||
1165 | if (likely(!link_congested(l_ptr))) { | ||
1166 | if (likely(msg_size(msg) <= link_max_pkt(l_ptr))) { | ||
1167 | if (likely(list_empty(&l_ptr->b_ptr->cong_links))) { | ||
1168 | link_add_to_outqueue(l_ptr, buf, msg); | ||
1169 | if (likely(bearer_send(l_ptr->b_ptr, buf, | ||
1170 | &l_ptr->media_addr))) { | ||
1171 | l_ptr->unacked_window = 0; | ||
1172 | msg_dbg(msg,"SENT_FAST:"); | ||
1173 | return res; | ||
1174 | } | ||
1175 | dbg("failed sent fast...\n"); | ||
1176 | bearer_schedule(l_ptr->b_ptr, l_ptr); | ||
1177 | l_ptr->stats.bearer_congs++; | ||
1178 | l_ptr->next_out = buf; | ||
1179 | return res; | ||
1180 | } | ||
1181 | } | ||
1182 | else | ||
1183 | *used_max_pkt = link_max_pkt(l_ptr); | ||
1184 | } | ||
1185 | return link_send_buf(l_ptr, buf); /* All other cases */ | ||
1186 | } | ||
1187 | |||
1188 | /* | ||
1189 | * tipc_send_buf_fast: Entry for data messages where the | ||
1190 | * destination node is known and the header is complete, | ||
1191 | * inclusive total message length. | ||
1192 | * Returns user data length. | ||
1193 | */ | ||
1194 | int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode) | ||
1195 | { | ||
1196 | struct link *l_ptr; | ||
1197 | struct node *n_ptr; | ||
1198 | int res; | ||
1199 | u32 selector = msg_origport(buf_msg(buf)) & 1; | ||
1200 | u32 dummy; | ||
1201 | |||
1202 | if (destnode == tipc_own_addr) | ||
1203 | return port_recv_msg(buf); | ||
1204 | |||
1205 | read_lock_bh(&net_lock); | ||
1206 | n_ptr = node_select(destnode, selector); | ||
1207 | if (likely(n_ptr)) { | ||
1208 | node_lock(n_ptr); | ||
1209 | l_ptr = n_ptr->active_links[selector]; | ||
1210 | dbg("send_fast: buf %x selected %x, destnode = %x\n", | ||
1211 | buf, l_ptr, destnode); | ||
1212 | if (likely(l_ptr)) { | ||
1213 | res = link_send_buf_fast(l_ptr, buf, &dummy); | ||
1214 | node_unlock(n_ptr); | ||
1215 | read_unlock_bh(&net_lock); | ||
1216 | return res; | ||
1217 | } | ||
1218 | node_unlock(n_ptr); | ||
1219 | } | ||
1220 | read_unlock_bh(&net_lock); | ||
1221 | res = msg_data_sz(buf_msg(buf)); | ||
1222 | tipc_reject_msg(buf, TIPC_ERR_NO_NODE); | ||
1223 | return res; | ||
1224 | } | ||
1225 | |||
1226 | |||
1227 | /* | ||
1228 | * link_send_sections_fast: Entry for messages where the | ||
1229 | * destination processor is known and the header is complete, | ||
1230 | * except for total message length. | ||
1231 | * Returns user data length or errno. | ||
1232 | */ | ||
1233 | int link_send_sections_fast(struct port *sender, | ||
1234 | struct iovec const *msg_sect, | ||
1235 | const u32 num_sect, | ||
1236 | u32 destaddr) | ||
1237 | { | ||
1238 | struct tipc_msg *hdr = &sender->publ.phdr; | ||
1239 | struct link *l_ptr; | ||
1240 | struct sk_buff *buf; | ||
1241 | struct node *node; | ||
1242 | int res; | ||
1243 | u32 selector = msg_origport(hdr) & 1; | ||
1244 | |||
1245 | assert(destaddr != tipc_own_addr); | ||
1246 | |||
1247 | again: | ||
1248 | /* | ||
1249 | * Try building message using port's max_pkt hint. | ||
1250 | * (Must not hold any locks while building message.) | ||
1251 | */ | ||
1252 | |||
1253 | res = msg_build(hdr, msg_sect, num_sect, sender->max_pkt, | ||
1254 | !sender->user_port, &buf); | ||
1255 | |||
1256 | read_lock_bh(&net_lock); | ||
1257 | node = node_select(destaddr, selector); | ||
1258 | if (likely(node)) { | ||
1259 | node_lock(node); | ||
1260 | l_ptr = node->active_links[selector]; | ||
1261 | if (likely(l_ptr)) { | ||
1262 | if (likely(buf)) { | ||
1263 | res = link_send_buf_fast(l_ptr, buf, | ||
1264 | &sender->max_pkt); | ||
1265 | if (unlikely(res < 0)) | ||
1266 | buf_discard(buf); | ||
1267 | exit: | ||
1268 | node_unlock(node); | ||
1269 | read_unlock_bh(&net_lock); | ||
1270 | return res; | ||
1271 | } | ||
1272 | |||
1273 | /* Exit if build request was invalid */ | ||
1274 | |||
1275 | if (unlikely(res < 0)) | ||
1276 | goto exit; | ||
1277 | |||
1278 | /* Exit if link (or bearer) is congested */ | ||
1279 | |||
1280 | if (link_congested(l_ptr) || | ||
1281 | !list_empty(&l_ptr->b_ptr->cong_links)) { | ||
1282 | res = link_schedule_port(l_ptr, | ||
1283 | sender->publ.ref, res); | ||
1284 | goto exit; | ||
1285 | } | ||
1286 | |||
1287 | /* | ||
1288 | * Message size exceeds max_pkt hint; update hint, | ||
1289 | * then re-try fast path or fragment the message | ||
1290 | */ | ||
1291 | |||
1292 | sender->max_pkt = link_max_pkt(l_ptr); | ||
1293 | node_unlock(node); | ||
1294 | read_unlock_bh(&net_lock); | ||
1295 | |||
1296 | |||
1297 | if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) | ||
1298 | goto again; | ||
1299 | |||
1300 | return link_send_sections_long(sender, msg_sect, | ||
1301 | num_sect, destaddr); | ||
1302 | } | ||
1303 | node_unlock(node); | ||
1304 | } | ||
1305 | read_unlock_bh(&net_lock); | ||
1306 | |||
1307 | /* Couldn't find a link to the destination node */ | ||
1308 | |||
1309 | if (buf) | ||
1310 | return tipc_reject_msg(buf, TIPC_ERR_NO_NODE); | ||
1311 | if (res >= 0) | ||
1312 | return port_reject_sections(sender, hdr, msg_sect, num_sect, | ||
1313 | TIPC_ERR_NO_NODE); | ||
1314 | return res; | ||
1315 | } | ||
1316 | |||
1317 | /* | ||
1318 | * link_send_sections_long(): Entry for long messages where the | ||
1319 | * destination node is known and the header is complete, | ||
1320 | * inclusive total message length. | ||
1321 | * Link and bearer congestion status have been checked to be ok, | ||
1322 | * and are ignored if they change. | ||
1323 | * | ||
1324 | * Note that fragments do not use the full link MTU so that they won't have | ||
1325 | * to undergo refragmentation if link changeover causes them to be sent | ||
1326 | * over another link with an additional tunnel header added as prefix. | ||
1327 | * (Refragmentation will still occur if the other link has a smaller MTU.) | ||
1328 | * | ||
1329 | * Returns user data length or errno. | ||
1330 | */ | ||
1331 | static int link_send_sections_long(struct port *sender, | ||
1332 | struct iovec const *msg_sect, | ||
1333 | u32 num_sect, | ||
1334 | u32 destaddr) | ||
1335 | { | ||
1336 | struct link *l_ptr; | ||
1337 | struct node *node; | ||
1338 | struct tipc_msg *hdr = &sender->publ.phdr; | ||
1339 | u32 dsz = msg_data_sz(hdr); | ||
1340 | u32 max_pkt,fragm_sz,rest; | ||
1341 | struct tipc_msg fragm_hdr; | ||
1342 | struct sk_buff *buf,*buf_chain,*prev; | ||
1343 | u32 fragm_crs,fragm_rest,hsz,sect_rest; | ||
1344 | const unchar *sect_crs; | ||
1345 | int curr_sect; | ||
1346 | u32 fragm_no; | ||
1347 | |||
1348 | again: | ||
1349 | fragm_no = 1; | ||
1350 | max_pkt = sender->max_pkt - INT_H_SIZE; | ||
1351 | /* leave room for tunnel header in case of link changeover */ | ||
1352 | fragm_sz = max_pkt - INT_H_SIZE; | ||
1353 | /* leave room for fragmentation header in each fragment */ | ||
1354 | rest = dsz; | ||
1355 | fragm_crs = 0; | ||
1356 | fragm_rest = 0; | ||
1357 | sect_rest = 0; | ||
1358 | sect_crs = 0; | ||
1359 | curr_sect = -1; | ||
1360 | |||
1361 | /* Prepare reusable fragment header: */ | ||
1362 | |||
1363 | msg_dbg(hdr, ">FRAGMENTING>"); | ||
1364 | msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, | ||
1365 | TIPC_OK, INT_H_SIZE, msg_destnode(hdr)); | ||
1366 | msg_set_link_selector(&fragm_hdr, sender->publ.ref); | ||
1367 | msg_set_size(&fragm_hdr, max_pkt); | ||
1368 | msg_set_fragm_no(&fragm_hdr, 1); | ||
1369 | |||
1370 | /* Prepare header of first fragment: */ | ||
1371 | |||
1372 | buf_chain = buf = buf_acquire(max_pkt); | ||
1373 | if (!buf) | ||
1374 | return -ENOMEM; | ||
1375 | buf->next = NULL; | ||
1376 | memcpy(buf->data, (unchar *)&fragm_hdr, INT_H_SIZE); | ||
1377 | hsz = msg_hdr_sz(hdr); | ||
1378 | memcpy(buf->data + INT_H_SIZE, (unchar *)hdr, hsz); | ||
1379 | msg_dbg(buf_msg(buf), ">BUILD>"); | ||
1380 | |||
1381 | /* Chop up message: */ | ||
1382 | |||
1383 | fragm_crs = INT_H_SIZE + hsz; | ||
1384 | fragm_rest = fragm_sz - hsz; | ||
1385 | |||
1386 | do { /* For all sections */ | ||
1387 | u32 sz; | ||
1388 | |||
1389 | if (!sect_rest) { | ||
1390 | sect_rest = msg_sect[++curr_sect].iov_len; | ||
1391 | sect_crs = (const unchar *)msg_sect[curr_sect].iov_base; | ||
1392 | } | ||
1393 | |||
1394 | if (sect_rest < fragm_rest) | ||
1395 | sz = sect_rest; | ||
1396 | else | ||
1397 | sz = fragm_rest; | ||
1398 | |||
1399 | if (likely(!sender->user_port)) { | ||
1400 | if (copy_from_user(buf->data + fragm_crs, sect_crs, sz)) { | ||
1401 | error: | ||
1402 | for (; buf_chain; buf_chain = buf) { | ||
1403 | buf = buf_chain->next; | ||
1404 | buf_discard(buf_chain); | ||
1405 | } | ||
1406 | return -EFAULT; | ||
1407 | } | ||
1408 | } else | ||
1409 | memcpy(buf->data + fragm_crs, sect_crs, sz); | ||
1410 | |||
1411 | sect_crs += sz; | ||
1412 | sect_rest -= sz; | ||
1413 | fragm_crs += sz; | ||
1414 | fragm_rest -= sz; | ||
1415 | rest -= sz; | ||
1416 | |||
1417 | if (!fragm_rest && rest) { | ||
1418 | |||
1419 | /* Initiate new fragment: */ | ||
1420 | if (rest <= fragm_sz) { | ||
1421 | fragm_sz = rest; | ||
1422 | msg_set_type(&fragm_hdr,LAST_FRAGMENT); | ||
1423 | } else { | ||
1424 | msg_set_type(&fragm_hdr, FRAGMENT); | ||
1425 | } | ||
1426 | msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE); | ||
1427 | msg_set_fragm_no(&fragm_hdr, ++fragm_no); | ||
1428 | prev = buf; | ||
1429 | buf = buf_acquire(fragm_sz + INT_H_SIZE); | ||
1430 | if (!buf) | ||
1431 | goto error; | ||
1432 | |||
1433 | buf->next = NULL; | ||
1434 | prev->next = buf; | ||
1435 | memcpy(buf->data, (unchar *)&fragm_hdr, INT_H_SIZE); | ||
1436 | fragm_crs = INT_H_SIZE; | ||
1437 | fragm_rest = fragm_sz; | ||
1438 | msg_dbg(buf_msg(buf)," >BUILD>"); | ||
1439 | } | ||
1440 | } | ||
1441 | while (rest > 0); | ||
1442 | |||
1443 | /* | ||
1444 | * Now we have a buffer chain. Select a link and check | ||
1445 | * that packet size is still OK | ||
1446 | */ | ||
1447 | node = node_select(destaddr, sender->publ.ref & 1); | ||
1448 | if (likely(node)) { | ||
1449 | node_lock(node); | ||
1450 | l_ptr = node->active_links[sender->publ.ref & 1]; | ||
1451 | if (!l_ptr) { | ||
1452 | node_unlock(node); | ||
1453 | goto reject; | ||
1454 | } | ||
1455 | if (link_max_pkt(l_ptr) < max_pkt) { | ||
1456 | sender->max_pkt = link_max_pkt(l_ptr); | ||
1457 | node_unlock(node); | ||
1458 | for (; buf_chain; buf_chain = buf) { | ||
1459 | buf = buf_chain->next; | ||
1460 | buf_discard(buf_chain); | ||
1461 | } | ||
1462 | goto again; | ||
1463 | } | ||
1464 | } else { | ||
1465 | reject: | ||
1466 | for (; buf_chain; buf_chain = buf) { | ||
1467 | buf = buf_chain->next; | ||
1468 | buf_discard(buf_chain); | ||
1469 | } | ||
1470 | return port_reject_sections(sender, hdr, msg_sect, num_sect, | ||
1471 | TIPC_ERR_NO_NODE); | ||
1472 | } | ||
1473 | |||
1474 | /* Append whole chain to send queue: */ | ||
1475 | |||
1476 | buf = buf_chain; | ||
1477 | l_ptr->long_msg_seq_no = mod(l_ptr->long_msg_seq_no + 1); | ||
1478 | if (!l_ptr->next_out) | ||
1479 | l_ptr->next_out = buf_chain; | ||
1480 | l_ptr->stats.sent_fragmented++; | ||
1481 | while (buf) { | ||
1482 | struct sk_buff *next = buf->next; | ||
1483 | struct tipc_msg *msg = buf_msg(buf); | ||
1484 | |||
1485 | l_ptr->stats.sent_fragments++; | ||
1486 | msg_set_long_msgno(msg, l_ptr->long_msg_seq_no); | ||
1487 | link_add_to_outqueue(l_ptr, buf, msg); | ||
1488 | msg_dbg(msg, ">ADD>"); | ||
1489 | buf = next; | ||
1490 | } | ||
1491 | |||
1492 | /* Send it, if possible: */ | ||
1493 | |||
1494 | link_push_queue(l_ptr); | ||
1495 | node_unlock(node); | ||
1496 | return dsz; | ||
1497 | } | ||
1498 | |||
1499 | /* | ||
1500 | * link_push_packet: Push one unsent packet to the media | ||
1501 | */ | ||
1502 | u32 link_push_packet(struct link *l_ptr) | ||
1503 | { | ||
1504 | struct sk_buff *buf = l_ptr->first_out; | ||
1505 | u32 r_q_size = l_ptr->retransm_queue_size; | ||
1506 | u32 r_q_head = l_ptr->retransm_queue_head; | ||
1507 | |||
1508 | /* Step to position where retransmission failed, if any, */ | ||
1509 | /* consider that buffers may have been released in meantime */ | ||
1510 | |||
1511 | if (r_q_size && buf) { | ||
1512 | u32 last = lesser(mod(r_q_head + r_q_size), | ||
1513 | link_last_sent(l_ptr)); | ||
1514 | u32 first = msg_seqno(buf_msg(buf)); | ||
1515 | |||
1516 | while (buf && less(first, r_q_head)) { | ||
1517 | first = mod(first + 1); | ||
1518 | buf = buf->next; | ||
1519 | } | ||
1520 | l_ptr->retransm_queue_head = r_q_head = first; | ||
1521 | l_ptr->retransm_queue_size = r_q_size = mod(last - first); | ||
1522 | } | ||
1523 | |||
1524 | /* Continue retransmission now, if there is anything: */ | ||
1525 | |||
1526 | if (r_q_size && buf && !skb_cloned(buf)) { | ||
1527 | msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); | ||
1528 | msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); | ||
1529 | if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { | ||
1530 | msg_dbg(buf_msg(buf), ">DEF-RETR>"); | ||
1531 | l_ptr->retransm_queue_head = mod(++r_q_head); | ||
1532 | l_ptr->retransm_queue_size = --r_q_size; | ||
1533 | l_ptr->stats.retransmitted++; | ||
1534 | return TIPC_OK; | ||
1535 | } else { | ||
1536 | l_ptr->stats.bearer_congs++; | ||
1537 | msg_dbg(buf_msg(buf), "|>DEF-RETR>"); | ||
1538 | return PUSH_FAILED; | ||
1539 | } | ||
1540 | } | ||
1541 | |||
1542 | /* Send deferred protocol message, if any: */ | ||
1543 | |||
1544 | buf = l_ptr->proto_msg_queue; | ||
1545 | if (buf) { | ||
1546 | msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); | ||
1547 | msg_set_bcast_ack(buf_msg(buf),l_ptr->owner->bclink.last_in); | ||
1548 | if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { | ||
1549 | msg_dbg(buf_msg(buf), ">DEF-PROT>"); | ||
1550 | l_ptr->unacked_window = 0; | ||
1551 | buf_discard(buf); | ||
1552 | l_ptr->proto_msg_queue = 0; | ||
1553 | return TIPC_OK; | ||
1554 | } else { | ||
1555 | msg_dbg(buf_msg(buf), "|>DEF-PROT>"); | ||
1556 | l_ptr->stats.bearer_congs++; | ||
1557 | return PUSH_FAILED; | ||
1558 | } | ||
1559 | } | ||
1560 | |||
1561 | /* Send one deferred data message, if send window not full: */ | ||
1562 | |||
1563 | buf = l_ptr->next_out; | ||
1564 | if (buf) { | ||
1565 | struct tipc_msg *msg = buf_msg(buf); | ||
1566 | u32 next = msg_seqno(msg); | ||
1567 | u32 first = msg_seqno(buf_msg(l_ptr->first_out)); | ||
1568 | |||
1569 | if (mod(next - first) < l_ptr->queue_limit[0]) { | ||
1570 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); | ||
1571 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | ||
1572 | if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { | ||
1573 | if (msg_user(msg) == MSG_BUNDLER) | ||
1574 | msg_set_type(msg, CLOSED_MSG); | ||
1575 | msg_dbg(msg, ">PUSH-DATA>"); | ||
1576 | l_ptr->next_out = buf->next; | ||
1577 | return TIPC_OK; | ||
1578 | } else { | ||
1579 | msg_dbg(msg, "|PUSH-DATA|"); | ||
1580 | l_ptr->stats.bearer_congs++; | ||
1581 | return PUSH_FAILED; | ||
1582 | } | ||
1583 | } | ||
1584 | } | ||
1585 | return PUSH_FINISHED; | ||
1586 | } | ||
1587 | |||
1588 | /* | ||
1589 | * push_queue(): push out the unsent messages of a link where | ||
1590 | * congestion has abated. Node is locked | ||
1591 | */ | ||
1592 | void link_push_queue(struct link *l_ptr) | ||
1593 | { | ||
1594 | u32 res; | ||
1595 | |||
1596 | if (bearer_congested(l_ptr->b_ptr, l_ptr)) | ||
1597 | return; | ||
1598 | |||
1599 | do { | ||
1600 | res = link_push_packet(l_ptr); | ||
1601 | } | ||
1602 | while (res == TIPC_OK); | ||
1603 | if (res == PUSH_FAILED) | ||
1604 | bearer_schedule(l_ptr->b_ptr, l_ptr); | ||
1605 | } | ||
1606 | |||
1607 | void link_retransmit(struct link *l_ptr, struct sk_buff *buf, | ||
1608 | u32 retransmits) | ||
1609 | { | ||
1610 | struct tipc_msg *msg; | ||
1611 | |||
1612 | dbg("Retransmitting %u in link %x\n", retransmits, l_ptr); | ||
1613 | |||
1614 | if (bearer_congested(l_ptr->b_ptr, l_ptr) && buf && !skb_cloned(buf)) { | ||
1615 | msg_dbg(buf_msg(buf), ">NO_RETR->BCONG>"); | ||
1616 | dbg_print_link(l_ptr, " "); | ||
1617 | l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf)); | ||
1618 | l_ptr->retransm_queue_size = retransmits; | ||
1619 | return; | ||
1620 | } | ||
1621 | while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) { | ||
1622 | msg = buf_msg(buf); | ||
1623 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); | ||
1624 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | ||
1625 | if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { | ||
1626 | /* Catch if retransmissions fail repeatedly: */ | ||
1627 | if (l_ptr->last_retransmitted == msg_seqno(msg)) { | ||
1628 | if (++l_ptr->stale_count > 100) { | ||
1629 | msg_print(CONS, buf_msg(buf), ">RETR>"); | ||
1630 | info("...Retransmitted %u times\n", | ||
1631 | l_ptr->stale_count); | ||
1632 | link_print(l_ptr, CONS, "Resetting Link\n");; | ||
1633 | link_reset(l_ptr); | ||
1634 | break; | ||
1635 | } | ||
1636 | } else { | ||
1637 | l_ptr->stale_count = 0; | ||
1638 | } | ||
1639 | l_ptr->last_retransmitted = msg_seqno(msg); | ||
1640 | |||
1641 | msg_dbg(buf_msg(buf), ">RETR>"); | ||
1642 | buf = buf->next; | ||
1643 | retransmits--; | ||
1644 | l_ptr->stats.retransmitted++; | ||
1645 | } else { | ||
1646 | bearer_schedule(l_ptr->b_ptr, l_ptr); | ||
1647 | l_ptr->stats.bearer_congs++; | ||
1648 | l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf)); | ||
1649 | l_ptr->retransm_queue_size = retransmits; | ||
1650 | return; | ||
1651 | } | ||
1652 | } | ||
1653 | l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0; | ||
1654 | } | ||
1655 | |||
1656 | /* | ||
1657 | * link_recv_non_seq: Receive packets which are outside | ||
1658 | * the link sequence flow | ||
1659 | */ | ||
1660 | |||
1661 | static void link_recv_non_seq(struct sk_buff *buf) | ||
1662 | { | ||
1663 | struct tipc_msg *msg = buf_msg(buf); | ||
1664 | |||
1665 | if (msg_user(msg) == LINK_CONFIG) | ||
1666 | disc_recv_msg(buf); | ||
1667 | else | ||
1668 | bclink_recv_pkt(buf); | ||
1669 | } | ||
1670 | |||
1671 | /** | ||
1672 | * link_insert_deferred_queue - insert deferred messages back into receive chain | ||
1673 | */ | ||
1674 | |||
1675 | static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr, | ||
1676 | struct sk_buff *buf) | ||
1677 | { | ||
1678 | u32 seq_no; | ||
1679 | |||
1680 | if (l_ptr->oldest_deferred_in == NULL) | ||
1681 | return buf; | ||
1682 | |||
1683 | seq_no = msg_seqno(buf_msg(l_ptr->oldest_deferred_in)); | ||
1684 | if (seq_no == mod(l_ptr->next_in_no)) { | ||
1685 | l_ptr->newest_deferred_in->next = buf; | ||
1686 | buf = l_ptr->oldest_deferred_in; | ||
1687 | l_ptr->oldest_deferred_in = NULL; | ||
1688 | l_ptr->deferred_inqueue_sz = 0; | ||
1689 | } | ||
1690 | return buf; | ||
1691 | } | ||
1692 | |||
1693 | void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) | ||
1694 | { | ||
1695 | read_lock_bh(&net_lock); | ||
1696 | while (head) { | ||
1697 | struct bearer *b_ptr; | ||
1698 | struct node *n_ptr; | ||
1699 | struct link *l_ptr; | ||
1700 | struct sk_buff *crs; | ||
1701 | struct sk_buff *buf = head; | ||
1702 | struct tipc_msg *msg = buf_msg(buf); | ||
1703 | u32 seq_no = msg_seqno(msg); | ||
1704 | u32 ackd = msg_ack(msg); | ||
1705 | u32 released = 0; | ||
1706 | int type; | ||
1707 | |||
1708 | b_ptr = (struct bearer *)tb_ptr; | ||
1709 | TIPC_SKB_CB(buf)->handle = b_ptr; | ||
1710 | |||
1711 | head = head->next; | ||
1712 | if (unlikely(msg_version(msg) != TIPC_VERSION)) | ||
1713 | goto cont; | ||
1714 | #if 0 | ||
1715 | if (msg_user(msg) != LINK_PROTOCOL) | ||
1716 | #endif | ||
1717 | msg_dbg(msg,"<REC<"); | ||
1718 | |||
1719 | if (unlikely(msg_non_seq(msg))) { | ||
1720 | link_recv_non_seq(buf); | ||
1721 | continue; | ||
1722 | } | ||
1723 | n_ptr = node_find(msg_prevnode(msg)); | ||
1724 | if (unlikely(!n_ptr)) | ||
1725 | goto cont; | ||
1726 | |||
1727 | node_lock(n_ptr); | ||
1728 | l_ptr = n_ptr->links[b_ptr->identity]; | ||
1729 | if (unlikely(!l_ptr)) { | ||
1730 | node_unlock(n_ptr); | ||
1731 | goto cont; | ||
1732 | } | ||
1733 | /* | ||
1734 | * Release acked messages | ||
1735 | */ | ||
1736 | if (less(n_ptr->bclink.acked, msg_bcast_ack(msg))) { | ||
1737 | if (node_is_up(n_ptr) && n_ptr->bclink.supported) | ||
1738 | bclink_acknowledge(n_ptr, msg_bcast_ack(msg)); | ||
1739 | } | ||
1740 | |||
1741 | crs = l_ptr->first_out; | ||
1742 | while ((crs != l_ptr->next_out) && | ||
1743 | less_eq(msg_seqno(buf_msg(crs)), ackd)) { | ||
1744 | struct sk_buff *next = crs->next; | ||
1745 | |||
1746 | buf_discard(crs); | ||
1747 | crs = next; | ||
1748 | released++; | ||
1749 | } | ||
1750 | if (released) { | ||
1751 | l_ptr->first_out = crs; | ||
1752 | l_ptr->out_queue_size -= released; | ||
1753 | } | ||
1754 | if (unlikely(l_ptr->next_out)) | ||
1755 | link_push_queue(l_ptr); | ||
1756 | if (unlikely(!list_empty(&l_ptr->waiting_ports))) | ||
1757 | link_wakeup_ports(l_ptr, 0); | ||
1758 | if (unlikely(++l_ptr->unacked_window >= TIPC_MIN_LINK_WIN)) { | ||
1759 | l_ptr->stats.sent_acks++; | ||
1760 | link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); | ||
1761 | } | ||
1762 | |||
1763 | protocol_check: | ||
1764 | if (likely(link_working_working(l_ptr))) { | ||
1765 | if (likely(seq_no == mod(l_ptr->next_in_no))) { | ||
1766 | l_ptr->next_in_no++; | ||
1767 | if (unlikely(l_ptr->oldest_deferred_in)) | ||
1768 | head = link_insert_deferred_queue(l_ptr, | ||
1769 | head); | ||
1770 | if (likely(msg_is_dest(msg, tipc_own_addr))) { | ||
1771 | deliver: | ||
1772 | if (likely(msg_isdata(msg))) { | ||
1773 | node_unlock(n_ptr); | ||
1774 | port_recv_msg(buf); | ||
1775 | continue; | ||
1776 | } | ||
1777 | switch (msg_user(msg)) { | ||
1778 | case MSG_BUNDLER: | ||
1779 | l_ptr->stats.recv_bundles++; | ||
1780 | l_ptr->stats.recv_bundled += | ||
1781 | msg_msgcnt(msg); | ||
1782 | node_unlock(n_ptr); | ||
1783 | link_recv_bundle(buf); | ||
1784 | continue; | ||
1785 | case ROUTE_DISTRIBUTOR: | ||
1786 | node_unlock(n_ptr); | ||
1787 | cluster_recv_routing_table(buf); | ||
1788 | continue; | ||
1789 | case NAME_DISTRIBUTOR: | ||
1790 | node_unlock(n_ptr); | ||
1791 | named_recv(buf); | ||
1792 | continue; | ||
1793 | case CONN_MANAGER: | ||
1794 | node_unlock(n_ptr); | ||
1795 | port_recv_proto_msg(buf); | ||
1796 | continue; | ||
1797 | case MSG_FRAGMENTER: | ||
1798 | l_ptr->stats.recv_fragments++; | ||
1799 | if (link_recv_fragment( | ||
1800 | &l_ptr->defragm_buf, | ||
1801 | &buf, &msg)) { | ||
1802 | l_ptr->stats.recv_fragmented++; | ||
1803 | goto deliver; | ||
1804 | } | ||
1805 | break; | ||
1806 | case CHANGEOVER_PROTOCOL: | ||
1807 | type = msg_type(msg); | ||
1808 | if (link_recv_changeover_msg( | ||
1809 | &l_ptr, &buf)) { | ||
1810 | msg = buf_msg(buf); | ||
1811 | seq_no = msg_seqno(msg); | ||
1812 | TIPC_SKB_CB(buf)->handle | ||
1813 | = b_ptr; | ||
1814 | if (type == ORIGINAL_MSG) | ||
1815 | goto deliver; | ||
1816 | goto protocol_check; | ||
1817 | } | ||
1818 | break; | ||
1819 | } | ||
1820 | } | ||
1821 | node_unlock(n_ptr); | ||
1822 | net_route_msg(buf); | ||
1823 | continue; | ||
1824 | } | ||
1825 | link_handle_out_of_seq_msg(l_ptr, buf); | ||
1826 | head = link_insert_deferred_queue(l_ptr, head); | ||
1827 | node_unlock(n_ptr); | ||
1828 | continue; | ||
1829 | } | ||
1830 | |||
1831 | if (msg_user(msg) == LINK_PROTOCOL) { | ||
1832 | link_recv_proto_msg(l_ptr, buf); | ||
1833 | head = link_insert_deferred_queue(l_ptr, head); | ||
1834 | node_unlock(n_ptr); | ||
1835 | continue; | ||
1836 | } | ||
1837 | msg_dbg(msg,"NSEQ<REC<"); | ||
1838 | link_state_event(l_ptr, TRAFFIC_MSG_EVT); | ||
1839 | |||
1840 | if (link_working_working(l_ptr)) { | ||
1841 | /* Re-insert in front of queue */ | ||
1842 | msg_dbg(msg,"RECV-REINS:"); | ||
1843 | buf->next = head; | ||
1844 | head = buf; | ||
1845 | node_unlock(n_ptr); | ||
1846 | continue; | ||
1847 | } | ||
1848 | node_unlock(n_ptr); | ||
1849 | cont: | ||
1850 | buf_discard(buf); | ||
1851 | } | ||
1852 | read_unlock_bh(&net_lock); | ||
1853 | } | ||
1854 | |||
1855 | /* | ||
1856 | * link_defer_buf(): Sort a received out-of-sequence packet | ||
1857 | * into the deferred reception queue. | ||
1858 | * Returns the increase of the queue length,i.e. 0 or 1 | ||
1859 | */ | ||
1860 | |||
1861 | u32 link_defer_pkt(struct sk_buff **head, | ||
1862 | struct sk_buff **tail, | ||
1863 | struct sk_buff *buf) | ||
1864 | { | ||
1865 | struct sk_buff *prev = 0; | ||
1866 | struct sk_buff *crs = *head; | ||
1867 | u32 seq_no = msg_seqno(buf_msg(buf)); | ||
1868 | |||
1869 | buf->next = NULL; | ||
1870 | |||
1871 | /* Empty queue ? */ | ||
1872 | if (*head == NULL) { | ||
1873 | *head = *tail = buf; | ||
1874 | return 1; | ||
1875 | } | ||
1876 | |||
1877 | /* Last ? */ | ||
1878 | if (less(msg_seqno(buf_msg(*tail)), seq_no)) { | ||
1879 | (*tail)->next = buf; | ||
1880 | *tail = buf; | ||
1881 | return 1; | ||
1882 | } | ||
1883 | |||
1884 | /* Scan through queue and sort it in */ | ||
1885 | do { | ||
1886 | struct tipc_msg *msg = buf_msg(crs); | ||
1887 | |||
1888 | if (less(seq_no, msg_seqno(msg))) { | ||
1889 | buf->next = crs; | ||
1890 | if (prev) | ||
1891 | prev->next = buf; | ||
1892 | else | ||
1893 | *head = buf; | ||
1894 | return 1; | ||
1895 | } | ||
1896 | if (seq_no == msg_seqno(msg)) { | ||
1897 | break; | ||
1898 | } | ||
1899 | prev = crs; | ||
1900 | crs = crs->next; | ||
1901 | } | ||
1902 | while (crs); | ||
1903 | |||
1904 | /* Message is a duplicate of an existing message */ | ||
1905 | |||
1906 | buf_discard(buf); | ||
1907 | return 0; | ||
1908 | } | ||
1909 | |||
1910 | /** | ||
1911 | * link_handle_out_of_seq_msg - handle arrival of out-of-sequence packet | ||
1912 | */ | ||
1913 | |||
1914 | static void link_handle_out_of_seq_msg(struct link *l_ptr, | ||
1915 | struct sk_buff *buf) | ||
1916 | { | ||
1917 | u32 seq_no = msg_seqno(buf_msg(buf)); | ||
1918 | |||
1919 | if (likely(msg_user(buf_msg(buf)) == LINK_PROTOCOL)) { | ||
1920 | link_recv_proto_msg(l_ptr, buf); | ||
1921 | return; | ||
1922 | } | ||
1923 | |||
1924 | dbg("rx OOS msg: seq_no %u, expecting %u (%u)\n", | ||
1925 | seq_no, mod(l_ptr->next_in_no), l_ptr->next_in_no); | ||
1926 | |||
1927 | /* Record OOS packet arrival (force mismatch on next timeout) */ | ||
1928 | |||
1929 | l_ptr->checkpoint--; | ||
1930 | |||
1931 | /* | ||
1932 | * Discard packet if a duplicate; otherwise add it to deferred queue | ||
1933 | * and notify peer of gap as per protocol specification | ||
1934 | */ | ||
1935 | |||
1936 | if (less(seq_no, mod(l_ptr->next_in_no))) { | ||
1937 | l_ptr->stats.duplicates++; | ||
1938 | buf_discard(buf); | ||
1939 | return; | ||
1940 | } | ||
1941 | |||
1942 | if (link_defer_pkt(&l_ptr->oldest_deferred_in, | ||
1943 | &l_ptr->newest_deferred_in, buf)) { | ||
1944 | l_ptr->deferred_inqueue_sz++; | ||
1945 | l_ptr->stats.deferred_recv++; | ||
1946 | if ((l_ptr->deferred_inqueue_sz % 16) == 1) | ||
1947 | link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); | ||
1948 | } else | ||
1949 | l_ptr->stats.duplicates++; | ||
1950 | } | ||
1951 | |||
1952 | /* | ||
1953 | * Send protocol message to the other endpoint. | ||
1954 | */ | ||
1955 | void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, | ||
1956 | u32 gap, u32 tolerance, u32 priority, u32 ack_mtu) | ||
1957 | { | ||
1958 | struct sk_buff *buf = 0; | ||
1959 | struct tipc_msg *msg = l_ptr->pmsg; | ||
1960 | u32 msg_size = sizeof(l_ptr->proto_msg); | ||
1961 | |||
1962 | if (link_blocked(l_ptr)) | ||
1963 | return; | ||
1964 | msg_set_type(msg, msg_typ); | ||
1965 | msg_set_net_plane(msg, l_ptr->b_ptr->net_plane); | ||
1966 | msg_set_bcast_ack(msg, mod(l_ptr->owner->bclink.last_in)); | ||
1967 | msg_set_last_bcast(msg, bclink_get_last_sent()); | ||
1968 | |||
1969 | if (msg_typ == STATE_MSG) { | ||
1970 | u32 next_sent = mod(l_ptr->next_out_no); | ||
1971 | |||
1972 | if (!link_is_up(l_ptr)) | ||
1973 | return; | ||
1974 | if (l_ptr->next_out) | ||
1975 | next_sent = msg_seqno(buf_msg(l_ptr->next_out)); | ||
1976 | msg_set_next_sent(msg, next_sent); | ||
1977 | if (l_ptr->oldest_deferred_in) { | ||
1978 | u32 rec = msg_seqno(buf_msg(l_ptr->oldest_deferred_in)); | ||
1979 | gap = mod(rec - mod(l_ptr->next_in_no)); | ||
1980 | } | ||
1981 | msg_set_seq_gap(msg, gap); | ||
1982 | if (gap) | ||
1983 | l_ptr->stats.sent_nacks++; | ||
1984 | msg_set_link_tolerance(msg, tolerance); | ||
1985 | msg_set_linkprio(msg, priority); | ||
1986 | msg_set_max_pkt(msg, ack_mtu); | ||
1987 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); | ||
1988 | msg_set_probe(msg, probe_msg != 0); | ||
1989 | if (probe_msg) { | ||
1990 | u32 mtu = l_ptr->max_pkt; | ||
1991 | |||
1992 | if ((mtu < l_ptr->max_pkt_target) && | ||
1993 | link_working_working(l_ptr) && | ||
1994 | l_ptr->fsm_msg_cnt) { | ||
1995 | msg_size = (mtu + (l_ptr->max_pkt_target - mtu)/2 + 2) & ~3; | ||
1996 | if (l_ptr->max_pkt_probes == 10) { | ||
1997 | l_ptr->max_pkt_target = (msg_size - 4); | ||
1998 | l_ptr->max_pkt_probes = 0; | ||
1999 | msg_size = (mtu + (l_ptr->max_pkt_target - mtu)/2 + 2) & ~3; | ||
2000 | } | ||
2001 | l_ptr->max_pkt_probes++; | ||
2002 | } | ||
2003 | |||
2004 | l_ptr->stats.sent_probes++; | ||
2005 | } | ||
2006 | l_ptr->stats.sent_states++; | ||
2007 | } else { /* RESET_MSG or ACTIVATE_MSG */ | ||
2008 | msg_set_ack(msg, mod(l_ptr->reset_checkpoint - 1)); | ||
2009 | msg_set_seq_gap(msg, 0); | ||
2010 | msg_set_next_sent(msg, 1); | ||
2011 | msg_set_link_tolerance(msg, l_ptr->tolerance); | ||
2012 | msg_set_linkprio(msg, l_ptr->priority); | ||
2013 | msg_set_max_pkt(msg, l_ptr->max_pkt_target); | ||
2014 | } | ||
2015 | |||
2016 | if (node_has_redundant_links(l_ptr->owner)) { | ||
2017 | msg_set_redundant_link(msg); | ||
2018 | } else { | ||
2019 | msg_clear_redundant_link(msg); | ||
2020 | } | ||
2021 | msg_set_linkprio(msg, l_ptr->priority); | ||
2022 | |||
2023 | /* Ensure sequence number will not fit : */ | ||
2024 | |||
2025 | msg_set_seqno(msg, mod(l_ptr->next_out_no + (0xffff/2))); | ||
2026 | |||
2027 | /* Congestion? */ | ||
2028 | |||
2029 | if (bearer_congested(l_ptr->b_ptr, l_ptr)) { | ||
2030 | if (!l_ptr->proto_msg_queue) { | ||
2031 | l_ptr->proto_msg_queue = | ||
2032 | buf_acquire(sizeof(l_ptr->proto_msg)); | ||
2033 | } | ||
2034 | buf = l_ptr->proto_msg_queue; | ||
2035 | if (!buf) | ||
2036 | return; | ||
2037 | memcpy(buf->data, (unchar *)msg, sizeof(l_ptr->proto_msg)); | ||
2038 | return; | ||
2039 | } | ||
2040 | msg_set_timestamp(msg, jiffies_to_msecs(jiffies)); | ||
2041 | |||
2042 | /* Message can be sent */ | ||
2043 | |||
2044 | msg_dbg(msg, ">>"); | ||
2045 | |||
2046 | buf = buf_acquire(msg_size); | ||
2047 | if (!buf) | ||
2048 | return; | ||
2049 | |||
2050 | memcpy(buf->data, (unchar *)msg, sizeof(l_ptr->proto_msg)); | ||
2051 | msg_set_size(buf_msg(buf), msg_size); | ||
2052 | |||
2053 | if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { | ||
2054 | l_ptr->unacked_window = 0; | ||
2055 | buf_discard(buf); | ||
2056 | return; | ||
2057 | } | ||
2058 | |||
2059 | /* New congestion */ | ||
2060 | bearer_schedule(l_ptr->b_ptr, l_ptr); | ||
2061 | l_ptr->proto_msg_queue = buf; | ||
2062 | l_ptr->stats.bearer_congs++; | ||
2063 | } | ||
2064 | |||
2065 | /* | ||
2066 | * Receive protocol message : | ||
2067 | * Note that network plane id propagates through the network, and may | ||
2068 | * change at any time. The node with lowest address rules | ||
2069 | */ | ||
2070 | |||
2071 | static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) | ||
2072 | { | ||
2073 | u32 rec_gap = 0; | ||
2074 | u32 max_pkt_info; | ||
2075 | u32 max_pkt_ack; | ||
2076 | u32 msg_tol; | ||
2077 | struct tipc_msg *msg = buf_msg(buf); | ||
2078 | |||
2079 | dbg("AT(%u):", jiffies_to_msecs(jiffies)); | ||
2080 | msg_dbg(msg, "<<"); | ||
2081 | if (link_blocked(l_ptr)) | ||
2082 | goto exit; | ||
2083 | |||
2084 | /* record unnumbered packet arrival (force mismatch on next timeout) */ | ||
2085 | |||
2086 | l_ptr->checkpoint--; | ||
2087 | |||
2088 | if (l_ptr->b_ptr->net_plane != msg_net_plane(msg)) | ||
2089 | if (tipc_own_addr > msg_prevnode(msg)) | ||
2090 | l_ptr->b_ptr->net_plane = msg_net_plane(msg); | ||
2091 | |||
2092 | l_ptr->owner->permit_changeover = msg_redundant_link(msg); | ||
2093 | |||
2094 | switch (msg_type(msg)) { | ||
2095 | |||
2096 | case RESET_MSG: | ||
2097 | if (!link_working_unknown(l_ptr) && l_ptr->peer_session) { | ||
2098 | if (msg_session(msg) == l_ptr->peer_session) { | ||
2099 | dbg("Duplicate RESET: %u<->%u\n", | ||
2100 | msg_session(msg), l_ptr->peer_session); | ||
2101 | break; /* duplicate: ignore */ | ||
2102 | } | ||
2103 | } | ||
2104 | /* fall thru' */ | ||
2105 | case ACTIVATE_MSG: | ||
2106 | /* Update link settings according other endpoint's values */ | ||
2107 | |||
2108 | strcpy((strrchr(l_ptr->name, ':') + 1), (char *)msg_data(msg)); | ||
2109 | |||
2110 | if ((msg_tol = msg_link_tolerance(msg)) && | ||
2111 | (msg_tol > l_ptr->tolerance)) | ||
2112 | link_set_supervision_props(l_ptr, msg_tol); | ||
2113 | |||
2114 | if (msg_linkprio(msg) > l_ptr->priority) | ||
2115 | l_ptr->priority = msg_linkprio(msg); | ||
2116 | |||
2117 | max_pkt_info = msg_max_pkt(msg); | ||
2118 | if (max_pkt_info) { | ||
2119 | if (max_pkt_info < l_ptr->max_pkt_target) | ||
2120 | l_ptr->max_pkt_target = max_pkt_info; | ||
2121 | if (l_ptr->max_pkt > l_ptr->max_pkt_target) | ||
2122 | l_ptr->max_pkt = l_ptr->max_pkt_target; | ||
2123 | } else { | ||
2124 | l_ptr->max_pkt = l_ptr->max_pkt_target; | ||
2125 | } | ||
2126 | l_ptr->owner->bclink.supported = (max_pkt_info != 0); | ||
2127 | |||
2128 | link_state_event(l_ptr, msg_type(msg)); | ||
2129 | |||
2130 | l_ptr->peer_session = msg_session(msg); | ||
2131 | l_ptr->peer_bearer_id = msg_bearer_id(msg); | ||
2132 | |||
2133 | /* Synchronize broadcast sequence numbers */ | ||
2134 | if (!node_has_redundant_links(l_ptr->owner)) { | ||
2135 | l_ptr->owner->bclink.last_in = mod(msg_last_bcast(msg)); | ||
2136 | } | ||
2137 | break; | ||
2138 | case STATE_MSG: | ||
2139 | |||
2140 | if ((msg_tol = msg_link_tolerance(msg))) | ||
2141 | link_set_supervision_props(l_ptr, msg_tol); | ||
2142 | |||
2143 | if (msg_linkprio(msg) && | ||
2144 | (msg_linkprio(msg) != l_ptr->priority)) { | ||
2145 | warn("Changing prio <%s>: %u->%u\n", | ||
2146 | l_ptr->name, l_ptr->priority, msg_linkprio(msg)); | ||
2147 | l_ptr->priority = msg_linkprio(msg); | ||
2148 | link_reset(l_ptr); /* Enforce change to take effect */ | ||
2149 | break; | ||
2150 | } | ||
2151 | link_state_event(l_ptr, TRAFFIC_MSG_EVT); | ||
2152 | l_ptr->stats.recv_states++; | ||
2153 | if (link_reset_unknown(l_ptr)) | ||
2154 | break; | ||
2155 | |||
2156 | if (less_eq(mod(l_ptr->next_in_no), msg_next_sent(msg))) { | ||
2157 | rec_gap = mod(msg_next_sent(msg) - | ||
2158 | mod(l_ptr->next_in_no)); | ||
2159 | } | ||
2160 | |||
2161 | max_pkt_ack = msg_max_pkt(msg); | ||
2162 | if (max_pkt_ack > l_ptr->max_pkt) { | ||
2163 | dbg("Link <%s> updated MTU %u -> %u\n", | ||
2164 | l_ptr->name, l_ptr->max_pkt, max_pkt_ack); | ||
2165 | l_ptr->max_pkt = max_pkt_ack; | ||
2166 | l_ptr->max_pkt_probes = 0; | ||
2167 | } | ||
2168 | |||
2169 | max_pkt_ack = 0; | ||
2170 | if (msg_probe(msg)) { | ||
2171 | l_ptr->stats.recv_probes++; | ||
2172 | if (msg_size(msg) > sizeof(l_ptr->proto_msg)) { | ||
2173 | max_pkt_ack = msg_size(msg); | ||
2174 | } | ||
2175 | } | ||
2176 | |||
2177 | /* Protocol message before retransmits, reduce loss risk */ | ||
2178 | |||
2179 | bclink_check_gap(l_ptr->owner, msg_last_bcast(msg)); | ||
2180 | |||
2181 | if (rec_gap || (msg_probe(msg))) { | ||
2182 | link_send_proto_msg(l_ptr, STATE_MSG, | ||
2183 | 0, rec_gap, 0, 0, max_pkt_ack); | ||
2184 | } | ||
2185 | if (msg_seq_gap(msg)) { | ||
2186 | msg_dbg(msg, "With Gap:"); | ||
2187 | l_ptr->stats.recv_nacks++; | ||
2188 | link_retransmit(l_ptr, l_ptr->first_out, | ||
2189 | msg_seq_gap(msg)); | ||
2190 | } | ||
2191 | break; | ||
2192 | default: | ||
2193 | msg_dbg(buf_msg(buf), "<DISCARDING UNKNOWN<"); | ||
2194 | } | ||
2195 | exit: | ||
2196 | buf_discard(buf); | ||
2197 | } | ||
2198 | |||
2199 | |||
2200 | /* | ||
2201 | * link_tunnel(): Send one message via a link belonging to | ||
2202 | * another bearer. Owner node is locked. | ||
2203 | */ | ||
2204 | void link_tunnel(struct link *l_ptr, | ||
2205 | struct tipc_msg *tunnel_hdr, | ||
2206 | struct tipc_msg *msg, | ||
2207 | u32 selector) | ||
2208 | { | ||
2209 | struct link *tunnel; | ||
2210 | struct sk_buff *buf; | ||
2211 | u32 length = msg_size(msg); | ||
2212 | |||
2213 | tunnel = l_ptr->owner->active_links[selector & 1]; | ||
2214 | if (!link_is_up(tunnel)) | ||
2215 | return; | ||
2216 | msg_set_size(tunnel_hdr, length + INT_H_SIZE); | ||
2217 | buf = buf_acquire(length + INT_H_SIZE); | ||
2218 | if (!buf) | ||
2219 | return; | ||
2220 | memcpy(buf->data, (unchar *)tunnel_hdr, INT_H_SIZE); | ||
2221 | memcpy(buf->data + INT_H_SIZE, (unchar *)msg, length); | ||
2222 | dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane); | ||
2223 | msg_dbg(buf_msg(buf), ">SEND>"); | ||
2224 | assert(tunnel); | ||
2225 | link_send_buf(tunnel, buf); | ||
2226 | } | ||
2227 | |||
2228 | |||
2229 | |||
2230 | /* | ||
2231 | * changeover(): Send whole message queue via the remaining link | ||
2232 | * Owner node is locked. | ||
2233 | */ | ||
2234 | |||
2235 | void link_changeover(struct link *l_ptr) | ||
2236 | { | ||
2237 | u32 msgcount = l_ptr->out_queue_size; | ||
2238 | struct sk_buff *crs = l_ptr->first_out; | ||
2239 | struct link *tunnel = l_ptr->owner->active_links[0]; | ||
2240 | int split_bundles = node_has_redundant_links(l_ptr->owner); | ||
2241 | struct tipc_msg tunnel_hdr; | ||
2242 | |||
2243 | if (!tunnel) | ||
2244 | return; | ||
2245 | |||
2246 | if (!l_ptr->owner->permit_changeover) | ||
2247 | return; | ||
2248 | |||
2249 | msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, | ||
2250 | ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); | ||
2251 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); | ||
2252 | msg_set_msgcnt(&tunnel_hdr, msgcount); | ||
2253 | if (!l_ptr->first_out) { | ||
2254 | struct sk_buff *buf; | ||
2255 | |||
2256 | assert(!msgcount); | ||
2257 | buf = buf_acquire(INT_H_SIZE); | ||
2258 | if (buf) { | ||
2259 | memcpy(buf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); | ||
2260 | msg_set_size(&tunnel_hdr, INT_H_SIZE); | ||
2261 | dbg("%c->%c:", l_ptr->b_ptr->net_plane, | ||
2262 | tunnel->b_ptr->net_plane); | ||
2263 | msg_dbg(&tunnel_hdr, "EMPTY>SEND>"); | ||
2264 | link_send_buf(tunnel, buf); | ||
2265 | } else { | ||
2266 | warn("Memory squeeze; link changeover failed\n"); | ||
2267 | } | ||
2268 | return; | ||
2269 | } | ||
2270 | while (crs) { | ||
2271 | struct tipc_msg *msg = buf_msg(crs); | ||
2272 | |||
2273 | if ((msg_user(msg) == MSG_BUNDLER) && split_bundles) { | ||
2274 | u32 msgcount = msg_msgcnt(msg); | ||
2275 | struct tipc_msg *m = msg_get_wrapped(msg); | ||
2276 | unchar* pos = (unchar*)m; | ||
2277 | |||
2278 | while (msgcount--) { | ||
2279 | msg_set_seqno(m,msg_seqno(msg)); | ||
2280 | link_tunnel(l_ptr, &tunnel_hdr, m, | ||
2281 | msg_link_selector(m)); | ||
2282 | pos += align(msg_size(m)); | ||
2283 | m = (struct tipc_msg *)pos; | ||
2284 | } | ||
2285 | } else { | ||
2286 | link_tunnel(l_ptr, &tunnel_hdr, msg, | ||
2287 | msg_link_selector(msg)); | ||
2288 | } | ||
2289 | crs = crs->next; | ||
2290 | } | ||
2291 | } | ||
2292 | |||
2293 | void link_send_duplicate(struct link *l_ptr, struct link *tunnel) | ||
2294 | { | ||
2295 | struct sk_buff *iter; | ||
2296 | struct tipc_msg tunnel_hdr; | ||
2297 | |||
2298 | msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, | ||
2299 | DUPLICATE_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); | ||
2300 | msg_set_msgcnt(&tunnel_hdr, l_ptr->out_queue_size); | ||
2301 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); | ||
2302 | iter = l_ptr->first_out; | ||
2303 | while (iter) { | ||
2304 | struct sk_buff *outbuf; | ||
2305 | struct tipc_msg *msg = buf_msg(iter); | ||
2306 | u32 length = msg_size(msg); | ||
2307 | |||
2308 | if (msg_user(msg) == MSG_BUNDLER) | ||
2309 | msg_set_type(msg, CLOSED_MSG); | ||
2310 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); /* Update */ | ||
2311 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | ||
2312 | msg_set_size(&tunnel_hdr, length + INT_H_SIZE); | ||
2313 | outbuf = buf_acquire(length + INT_H_SIZE); | ||
2314 | if (outbuf == NULL) { | ||
2315 | warn("Memory squeeze; buffer duplication failed\n"); | ||
2316 | return; | ||
2317 | } | ||
2318 | memcpy(outbuf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); | ||
2319 | memcpy(outbuf->data + INT_H_SIZE, iter->data, length); | ||
2320 | dbg("%c->%c:", l_ptr->b_ptr->net_plane, | ||
2321 | tunnel->b_ptr->net_plane); | ||
2322 | msg_dbg(buf_msg(outbuf), ">SEND>"); | ||
2323 | link_send_buf(tunnel, outbuf); | ||
2324 | if (!link_is_up(l_ptr)) | ||
2325 | return; | ||
2326 | iter = iter->next; | ||
2327 | } | ||
2328 | } | ||
2329 | |||
2330 | |||
2331 | |||
2332 | /** | ||
2333 | * buf_extract - extracts embedded TIPC message from another message | ||
2334 | * @skb: encapsulating message buffer | ||
2335 | * @from_pos: offset to extract from | ||
2336 | * | ||
2337 | * Returns a new message buffer containing an embedded message. The | ||
2338 | * encapsulating message itself is left unchanged. | ||
2339 | */ | ||
2340 | |||
2341 | static struct sk_buff *buf_extract(struct sk_buff *skb, u32 from_pos) | ||
2342 | { | ||
2343 | struct tipc_msg *msg = (struct tipc_msg *)(skb->data + from_pos); | ||
2344 | u32 size = msg_size(msg); | ||
2345 | struct sk_buff *eb; | ||
2346 | |||
2347 | eb = buf_acquire(size); | ||
2348 | if (eb) | ||
2349 | memcpy(eb->data, (unchar *)msg, size); | ||
2350 | return eb; | ||
2351 | } | ||
2352 | |||
2353 | /* | ||
2354 | * link_recv_changeover_msg(): Receive tunneled packet sent | ||
2355 | * via other link. Node is locked. Return extracted buffer. | ||
2356 | */ | ||
2357 | |||
2358 | static int link_recv_changeover_msg(struct link **l_ptr, | ||
2359 | struct sk_buff **buf) | ||
2360 | { | ||
2361 | struct sk_buff *tunnel_buf = *buf; | ||
2362 | struct link *dest_link; | ||
2363 | struct tipc_msg *msg; | ||
2364 | struct tipc_msg *tunnel_msg = buf_msg(tunnel_buf); | ||
2365 | u32 msg_typ = msg_type(tunnel_msg); | ||
2366 | u32 msg_count = msg_msgcnt(tunnel_msg); | ||
2367 | |||
2368 | dest_link = (*l_ptr)->owner->links[msg_bearer_id(tunnel_msg)]; | ||
2369 | assert(dest_link != *l_ptr); | ||
2370 | if (!dest_link) { | ||
2371 | msg_dbg(tunnel_msg, "NOLINK/<REC<"); | ||
2372 | goto exit; | ||
2373 | } | ||
2374 | dbg("%c<-%c:", dest_link->b_ptr->net_plane, | ||
2375 | (*l_ptr)->b_ptr->net_plane); | ||
2376 | *l_ptr = dest_link; | ||
2377 | msg = msg_get_wrapped(tunnel_msg); | ||
2378 | |||
2379 | if (msg_typ == DUPLICATE_MSG) { | ||
2380 | if (less(msg_seqno(msg), mod(dest_link->next_in_no))) { | ||
2381 | msg_dbg(tunnel_msg, "DROP/<REC<"); | ||
2382 | goto exit; | ||
2383 | } | ||
2384 | *buf = buf_extract(tunnel_buf,INT_H_SIZE); | ||
2385 | if (*buf == NULL) { | ||
2386 | warn("Memory squeeze; failed to extract msg\n"); | ||
2387 | goto exit; | ||
2388 | } | ||
2389 | msg_dbg(tunnel_msg, "TNL<REC<"); | ||
2390 | buf_discard(tunnel_buf); | ||
2391 | return 1; | ||
2392 | } | ||
2393 | |||
2394 | /* First original message ?: */ | ||
2395 | |||
2396 | if (link_is_up(dest_link)) { | ||
2397 | msg_dbg(tunnel_msg, "UP/FIRST/<REC<"); | ||
2398 | link_reset(dest_link); | ||
2399 | dest_link->exp_msg_count = msg_count; | ||
2400 | if (!msg_count) | ||
2401 | goto exit; | ||
2402 | } else if (dest_link->exp_msg_count == START_CHANGEOVER) { | ||
2403 | msg_dbg(tunnel_msg, "BLK/FIRST/<REC<"); | ||
2404 | dest_link->exp_msg_count = msg_count; | ||
2405 | if (!msg_count) | ||
2406 | goto exit; | ||
2407 | } | ||
2408 | |||
2409 | /* Receive original message */ | ||
2410 | |||
2411 | if (dest_link->exp_msg_count == 0) { | ||
2412 | msg_dbg(tunnel_msg, "OVERDUE/DROP/<REC<"); | ||
2413 | dbg_print_link(dest_link, "LINK:"); | ||
2414 | goto exit; | ||
2415 | } | ||
2416 | dest_link->exp_msg_count--; | ||
2417 | if (less(msg_seqno(msg), dest_link->reset_checkpoint)) { | ||
2418 | msg_dbg(tunnel_msg, "DROP/DUPL/<REC<"); | ||
2419 | goto exit; | ||
2420 | } else { | ||
2421 | *buf = buf_extract(tunnel_buf, INT_H_SIZE); | ||
2422 | if (*buf != NULL) { | ||
2423 | msg_dbg(tunnel_msg, "TNL<REC<"); | ||
2424 | buf_discard(tunnel_buf); | ||
2425 | return 1; | ||
2426 | } else { | ||
2427 | warn("Memory squeeze; dropped incoming msg\n"); | ||
2428 | } | ||
2429 | } | ||
2430 | exit: | ||
2431 | *buf = 0; | ||
2432 | buf_discard(tunnel_buf); | ||
2433 | return 0; | ||
2434 | } | ||
2435 | |||
2436 | /* | ||
2437 | * Bundler functionality: | ||
2438 | */ | ||
2439 | void link_recv_bundle(struct sk_buff *buf) | ||
2440 | { | ||
2441 | u32 msgcount = msg_msgcnt(buf_msg(buf)); | ||
2442 | u32 pos = INT_H_SIZE; | ||
2443 | struct sk_buff *obuf; | ||
2444 | |||
2445 | msg_dbg(buf_msg(buf), "<BNDL<: "); | ||
2446 | while (msgcount--) { | ||
2447 | obuf = buf_extract(buf, pos); | ||
2448 | if (obuf == NULL) { | ||
2449 | char addr_string[16]; | ||
2450 | |||
2451 | warn("Buffer allocation failure;\n"); | ||
2452 | warn(" incoming message(s) from %s lost\n", | ||
2453 | addr_string_fill(addr_string, | ||
2454 | msg_orignode(buf_msg(buf)))); | ||
2455 | return; | ||
2456 | }; | ||
2457 | pos += align(msg_size(buf_msg(obuf))); | ||
2458 | msg_dbg(buf_msg(obuf), " /"); | ||
2459 | net_route_msg(obuf); | ||
2460 | } | ||
2461 | buf_discard(buf); | ||
2462 | } | ||
2463 | |||
2464 | /* | ||
2465 | * Fragmentation/defragmentation: | ||
2466 | */ | ||
2467 | |||
2468 | |||
2469 | /* | ||
2470 | * link_send_long_buf: Entry for buffers needing fragmentation. | ||
2471 | * The buffer is complete, inclusive total message length. | ||
2472 | * Returns user data length. | ||
2473 | */ | ||
2474 | int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) | ||
2475 | { | ||
2476 | struct tipc_msg *inmsg = buf_msg(buf); | ||
2477 | struct tipc_msg fragm_hdr; | ||
2478 | u32 insize = msg_size(inmsg); | ||
2479 | u32 dsz = msg_data_sz(inmsg); | ||
2480 | unchar *crs = buf->data; | ||
2481 | u32 rest = insize; | ||
2482 | u32 pack_sz = link_max_pkt(l_ptr); | ||
2483 | u32 fragm_sz = pack_sz - INT_H_SIZE; | ||
2484 | u32 fragm_no = 1; | ||
2485 | u32 destaddr = msg_destnode(inmsg); | ||
2486 | |||
2487 | if (msg_short(inmsg)) | ||
2488 | destaddr = l_ptr->addr; | ||
2489 | |||
2490 | if (msg_routed(inmsg)) | ||
2491 | msg_set_prevnode(inmsg, tipc_own_addr); | ||
2492 | |||
2493 | /* Prepare reusable fragment header: */ | ||
2494 | |||
2495 | msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, | ||
2496 | TIPC_OK, INT_H_SIZE, destaddr); | ||
2497 | msg_set_link_selector(&fragm_hdr, msg_link_selector(inmsg)); | ||
2498 | msg_set_long_msgno(&fragm_hdr, mod(l_ptr->long_msg_seq_no++)); | ||
2499 | msg_set_fragm_no(&fragm_hdr, fragm_no); | ||
2500 | l_ptr->stats.sent_fragmented++; | ||
2501 | |||
2502 | /* Chop up message: */ | ||
2503 | |||
2504 | while (rest > 0) { | ||
2505 | struct sk_buff *fragm; | ||
2506 | |||
2507 | if (rest <= fragm_sz) { | ||
2508 | fragm_sz = rest; | ||
2509 | msg_set_type(&fragm_hdr, LAST_FRAGMENT); | ||
2510 | } | ||
2511 | fragm = buf_acquire(fragm_sz + INT_H_SIZE); | ||
2512 | if (fragm == NULL) { | ||
2513 | warn("Memory squeeze; failed to fragment msg\n"); | ||
2514 | dsz = -ENOMEM; | ||
2515 | goto exit; | ||
2516 | } | ||
2517 | msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE); | ||
2518 | memcpy(fragm->data, (unchar *)&fragm_hdr, INT_H_SIZE); | ||
2519 | memcpy(fragm->data + INT_H_SIZE, crs, fragm_sz); | ||
2520 | |||
2521 | /* Send queued messages first, if any: */ | ||
2522 | |||
2523 | l_ptr->stats.sent_fragments++; | ||
2524 | link_send_buf(l_ptr, fragm); | ||
2525 | if (!link_is_up(l_ptr)) | ||
2526 | return dsz; | ||
2527 | msg_set_fragm_no(&fragm_hdr, ++fragm_no); | ||
2528 | rest -= fragm_sz; | ||
2529 | crs += fragm_sz; | ||
2530 | msg_set_type(&fragm_hdr, FRAGMENT); | ||
2531 | } | ||
2532 | exit: | ||
2533 | buf_discard(buf); | ||
2534 | return dsz; | ||
2535 | } | ||
2536 | |||
2537 | /* | ||
2538 | * A pending message being re-assembled must store certain values | ||
2539 | * to handle subsequent fragments correctly. The following functions | ||
2540 | * help storing these values in unused, available fields in the | ||
2541 | * pending message. This makes dynamic memory allocation unecessary. | ||
2542 | */ | ||
2543 | |||
2544 | static inline u32 get_long_msg_seqno(struct sk_buff *buf) | ||
2545 | { | ||
2546 | return msg_seqno(buf_msg(buf)); | ||
2547 | } | ||
2548 | |||
2549 | static inline void set_long_msg_seqno(struct sk_buff *buf, u32 seqno) | ||
2550 | { | ||
2551 | msg_set_seqno(buf_msg(buf), seqno); | ||
2552 | } | ||
2553 | |||
2554 | static inline u32 get_fragm_size(struct sk_buff *buf) | ||
2555 | { | ||
2556 | return msg_ack(buf_msg(buf)); | ||
2557 | } | ||
2558 | |||
2559 | static inline void set_fragm_size(struct sk_buff *buf, u32 sz) | ||
2560 | { | ||
2561 | msg_set_ack(buf_msg(buf), sz); | ||
2562 | } | ||
2563 | |||
2564 | static inline u32 get_expected_frags(struct sk_buff *buf) | ||
2565 | { | ||
2566 | return msg_bcast_ack(buf_msg(buf)); | ||
2567 | } | ||
2568 | |||
2569 | static inline void set_expected_frags(struct sk_buff *buf, u32 exp) | ||
2570 | { | ||
2571 | msg_set_bcast_ack(buf_msg(buf), exp); | ||
2572 | } | ||
2573 | |||
2574 | static inline u32 get_timer_cnt(struct sk_buff *buf) | ||
2575 | { | ||
2576 | return msg_reroute_cnt(buf_msg(buf)); | ||
2577 | } | ||
2578 | |||
2579 | static inline void incr_timer_cnt(struct sk_buff *buf) | ||
2580 | { | ||
2581 | msg_incr_reroute_cnt(buf_msg(buf)); | ||
2582 | } | ||
2583 | |||
2584 | /* | ||
2585 | * link_recv_fragment(): Called with node lock on. Returns | ||
2586 | * the reassembled buffer if message is complete. | ||
2587 | */ | ||
2588 | int link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, | ||
2589 | struct tipc_msg **m) | ||
2590 | { | ||
2591 | struct sk_buff *prev = 0; | ||
2592 | struct sk_buff *fbuf = *fb; | ||
2593 | struct tipc_msg *fragm = buf_msg(fbuf); | ||
2594 | struct sk_buff *pbuf = *pending; | ||
2595 | u32 long_msg_seq_no = msg_long_msgno(fragm); | ||
2596 | |||
2597 | *fb = 0; | ||
2598 | msg_dbg(fragm,"FRG<REC<"); | ||
2599 | |||
2600 | /* Is there an incomplete message waiting for this fragment? */ | ||
2601 | |||
2602 | while (pbuf && ((msg_seqno(buf_msg(pbuf)) != long_msg_seq_no) | ||
2603 | || (msg_orignode(fragm) != msg_orignode(buf_msg(pbuf))))) { | ||
2604 | prev = pbuf; | ||
2605 | pbuf = pbuf->next; | ||
2606 | } | ||
2607 | |||
2608 | if (!pbuf && (msg_type(fragm) == FIRST_FRAGMENT)) { | ||
2609 | struct tipc_msg *imsg = (struct tipc_msg *)msg_data(fragm); | ||
2610 | u32 msg_sz = msg_size(imsg); | ||
2611 | u32 fragm_sz = msg_data_sz(fragm); | ||
2612 | u32 exp_fragm_cnt = msg_sz/fragm_sz + !!(msg_sz % fragm_sz); | ||
2613 | u32 max = TIPC_MAX_USER_MSG_SIZE + LONG_H_SIZE; | ||
2614 | if (msg_type(imsg) == TIPC_MCAST_MSG) | ||
2615 | max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE; | ||
2616 | if (msg_size(imsg) > max) { | ||
2617 | msg_dbg(fragm,"<REC<Oversized: "); | ||
2618 | buf_discard(fbuf); | ||
2619 | return 0; | ||
2620 | } | ||
2621 | pbuf = buf_acquire(msg_size(imsg)); | ||
2622 | if (pbuf != NULL) { | ||
2623 | pbuf->next = *pending; | ||
2624 | *pending = pbuf; | ||
2625 | memcpy(pbuf->data, (unchar *)imsg, msg_data_sz(fragm)); | ||
2626 | |||
2627 | /* Prepare buffer for subsequent fragments. */ | ||
2628 | |||
2629 | set_long_msg_seqno(pbuf, long_msg_seq_no); | ||
2630 | set_fragm_size(pbuf,fragm_sz); | ||
2631 | set_expected_frags(pbuf,exp_fragm_cnt - 1); | ||
2632 | } else { | ||
2633 | warn("Memory squeeze; got no defragmenting buffer\n"); | ||
2634 | } | ||
2635 | buf_discard(fbuf); | ||
2636 | return 0; | ||
2637 | } else if (pbuf && (msg_type(fragm) != FIRST_FRAGMENT)) { | ||
2638 | u32 dsz = msg_data_sz(fragm); | ||
2639 | u32 fsz = get_fragm_size(pbuf); | ||
2640 | u32 crs = ((msg_fragm_no(fragm) - 1) * fsz); | ||
2641 | u32 exp_frags = get_expected_frags(pbuf) - 1; | ||
2642 | memcpy(pbuf->data + crs, msg_data(fragm), dsz); | ||
2643 | buf_discard(fbuf); | ||
2644 | |||
2645 | /* Is message complete? */ | ||
2646 | |||
2647 | if (exp_frags == 0) { | ||
2648 | if (prev) | ||
2649 | prev->next = pbuf->next; | ||
2650 | else | ||
2651 | *pending = pbuf->next; | ||
2652 | msg_reset_reroute_cnt(buf_msg(pbuf)); | ||
2653 | *fb = pbuf; | ||
2654 | *m = buf_msg(pbuf); | ||
2655 | return 1; | ||
2656 | } | ||
2657 | set_expected_frags(pbuf,exp_frags); | ||
2658 | return 0; | ||
2659 | } | ||
2660 | dbg(" Discarding orphan fragment %x\n",fbuf); | ||
2661 | msg_dbg(fragm,"ORPHAN:"); | ||
2662 | dbg("Pending long buffers:\n"); | ||
2663 | dbg_print_buf_chain(*pending); | ||
2664 | buf_discard(fbuf); | ||
2665 | return 0; | ||
2666 | } | ||
2667 | |||
2668 | /** | ||
2669 | * link_check_defragm_bufs - flush stale incoming message fragments | ||
2670 | * @l_ptr: pointer to link | ||
2671 | */ | ||
2672 | |||
2673 | static void link_check_defragm_bufs(struct link *l_ptr) | ||
2674 | { | ||
2675 | struct sk_buff *prev = 0; | ||
2676 | struct sk_buff *next = 0; | ||
2677 | struct sk_buff *buf = l_ptr->defragm_buf; | ||
2678 | |||
2679 | if (!buf) | ||
2680 | return; | ||
2681 | if (!link_working_working(l_ptr)) | ||
2682 | return; | ||
2683 | while (buf) { | ||
2684 | u32 cnt = get_timer_cnt(buf); | ||
2685 | |||
2686 | next = buf->next; | ||
2687 | if (cnt < 4) { | ||
2688 | incr_timer_cnt(buf); | ||
2689 | prev = buf; | ||
2690 | } else { | ||
2691 | dbg(" Discarding incomplete long buffer\n"); | ||
2692 | msg_dbg(buf_msg(buf), "LONG:"); | ||
2693 | dbg_print_link(l_ptr, "curr:"); | ||
2694 | dbg("Pending long buffers:\n"); | ||
2695 | dbg_print_buf_chain(l_ptr->defragm_buf); | ||
2696 | if (prev) | ||
2697 | prev->next = buf->next; | ||
2698 | else | ||
2699 | l_ptr->defragm_buf = buf->next; | ||
2700 | buf_discard(buf); | ||
2701 | } | ||
2702 | buf = next; | ||
2703 | } | ||
2704 | } | ||
2705 | |||
2706 | |||
2707 | |||
2708 | static void link_set_supervision_props(struct link *l_ptr, u32 tolerance) | ||
2709 | { | ||
2710 | l_ptr->tolerance = tolerance; | ||
2711 | l_ptr->continuity_interval = | ||
2712 | ((tolerance / 4) > 500) ? 500 : tolerance / 4; | ||
2713 | l_ptr->abort_limit = tolerance / (l_ptr->continuity_interval / 4); | ||
2714 | } | ||
2715 | |||
2716 | |||
2717 | void link_set_queue_limits(struct link *l_ptr, u32 window) | ||
2718 | { | ||
2719 | /* Data messages from this node, inclusive FIRST_FRAGM */ | ||
2720 | l_ptr->queue_limit[DATA_LOW] = window; | ||
2721 | l_ptr->queue_limit[DATA_MEDIUM] = (window / 3) * 4; | ||
2722 | l_ptr->queue_limit[DATA_HIGH] = (window / 3) * 5; | ||
2723 | l_ptr->queue_limit[DATA_CRITICAL] = (window / 3) * 6; | ||
2724 | /* Transiting data messages,inclusive FIRST_FRAGM */ | ||
2725 | l_ptr->queue_limit[DATA_LOW + 4] = 300; | ||
2726 | l_ptr->queue_limit[DATA_MEDIUM + 4] = 600; | ||
2727 | l_ptr->queue_limit[DATA_HIGH + 4] = 900; | ||
2728 | l_ptr->queue_limit[DATA_CRITICAL + 4] = 1200; | ||
2729 | l_ptr->queue_limit[CONN_MANAGER] = 1200; | ||
2730 | l_ptr->queue_limit[ROUTE_DISTRIBUTOR] = 1200; | ||
2731 | l_ptr->queue_limit[CHANGEOVER_PROTOCOL] = 2500; | ||
2732 | l_ptr->queue_limit[NAME_DISTRIBUTOR] = 3000; | ||
2733 | /* FRAGMENT and LAST_FRAGMENT packets */ | ||
2734 | l_ptr->queue_limit[MSG_FRAGMENTER] = 4000; | ||
2735 | } | ||
2736 | |||
2737 | /** | ||
2738 | * link_find_link - locate link by name | ||
2739 | * @name - ptr to link name string | ||
2740 | * @node - ptr to area to be filled with ptr to associated node | ||
2741 | * | ||
2742 | * Caller must hold 'net_lock' to ensure node and bearer are not deleted; | ||
2743 | * this also prevents link deletion. | ||
2744 | * | ||
2745 | * Returns pointer to link (or 0 if invalid link name). | ||
2746 | */ | ||
2747 | |||
2748 | static struct link *link_find_link(const char *name, struct node **node) | ||
2749 | { | ||
2750 | struct link_name link_name_parts; | ||
2751 | struct bearer *b_ptr; | ||
2752 | struct link *l_ptr; | ||
2753 | |||
2754 | if (!link_name_validate(name, &link_name_parts)) | ||
2755 | return 0; | ||
2756 | |||
2757 | b_ptr = bearer_find_interface(link_name_parts.if_local); | ||
2758 | if (!b_ptr) | ||
2759 | return 0; | ||
2760 | |||
2761 | *node = node_find(link_name_parts.addr_peer); | ||
2762 | if (!*node) | ||
2763 | return 0; | ||
2764 | |||
2765 | l_ptr = (*node)->links[b_ptr->identity]; | ||
2766 | if (!l_ptr || strcmp(l_ptr->name, name)) | ||
2767 | return 0; | ||
2768 | |||
2769 | return l_ptr; | ||
2770 | } | ||
2771 | |||
2772 | struct sk_buff *link_cmd_config(const void *req_tlv_area, int req_tlv_space, | ||
2773 | u16 cmd) | ||
2774 | { | ||
2775 | struct tipc_link_config *args; | ||
2776 | u32 new_value; | ||
2777 | struct link *l_ptr; | ||
2778 | struct node *node; | ||
2779 | int res; | ||
2780 | |||
2781 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_CONFIG)) | ||
2782 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
2783 | |||
2784 | args = (struct tipc_link_config *)TLV_DATA(req_tlv_area); | ||
2785 | new_value = ntohl(args->value); | ||
2786 | |||
2787 | if (!strcmp(args->name, bc_link_name)) { | ||
2788 | if ((cmd == TIPC_CMD_SET_LINK_WINDOW) && | ||
2789 | (bclink_set_queue_limits(new_value) == 0)) | ||
2790 | return cfg_reply_none(); | ||
2791 | return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
2792 | " (cannot change setting on broadcast link)"); | ||
2793 | } | ||
2794 | |||
2795 | read_lock_bh(&net_lock); | ||
2796 | l_ptr = link_find_link(args->name, &node); | ||
2797 | if (!l_ptr) { | ||
2798 | read_unlock_bh(&net_lock); | ||
2799 | return cfg_reply_error_string("link not found"); | ||
2800 | } | ||
2801 | |||
2802 | node_lock(node); | ||
2803 | res = -EINVAL; | ||
2804 | switch (cmd) { | ||
2805 | case TIPC_CMD_SET_LINK_TOL: | ||
2806 | if ((new_value >= TIPC_MIN_LINK_TOL) && | ||
2807 | (new_value <= TIPC_MAX_LINK_TOL)) { | ||
2808 | link_set_supervision_props(l_ptr, new_value); | ||
2809 | link_send_proto_msg(l_ptr, STATE_MSG, | ||
2810 | 0, 0, new_value, 0, 0); | ||
2811 | res = TIPC_OK; | ||
2812 | } | ||
2813 | break; | ||
2814 | case TIPC_CMD_SET_LINK_PRI: | ||
2815 | if (new_value < TIPC_NUM_LINK_PRI) { | ||
2816 | l_ptr->priority = new_value; | ||
2817 | link_send_proto_msg(l_ptr, STATE_MSG, | ||
2818 | 0, 0, 0, new_value, 0); | ||
2819 | res = TIPC_OK; | ||
2820 | } | ||
2821 | break; | ||
2822 | case TIPC_CMD_SET_LINK_WINDOW: | ||
2823 | if ((new_value >= TIPC_MIN_LINK_WIN) && | ||
2824 | (new_value <= TIPC_MAX_LINK_WIN)) { | ||
2825 | link_set_queue_limits(l_ptr, new_value); | ||
2826 | res = TIPC_OK; | ||
2827 | } | ||
2828 | break; | ||
2829 | } | ||
2830 | node_unlock(node); | ||
2831 | |||
2832 | read_unlock_bh(&net_lock); | ||
2833 | if (res) | ||
2834 | return cfg_reply_error_string("cannot change link setting"); | ||
2835 | |||
2836 | return cfg_reply_none(); | ||
2837 | } | ||
2838 | |||
2839 | /** | ||
2840 | * link_reset_statistics - reset link statistics | ||
2841 | * @l_ptr: pointer to link | ||
2842 | */ | ||
2843 | |||
2844 | static void link_reset_statistics(struct link *l_ptr) | ||
2845 | { | ||
2846 | memset(&l_ptr->stats, 0, sizeof(l_ptr->stats)); | ||
2847 | l_ptr->stats.sent_info = l_ptr->next_out_no; | ||
2848 | l_ptr->stats.recv_info = l_ptr->next_in_no; | ||
2849 | } | ||
2850 | |||
2851 | struct sk_buff *link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space) | ||
2852 | { | ||
2853 | char *link_name; | ||
2854 | struct link *l_ptr; | ||
2855 | struct node *node; | ||
2856 | |||
2857 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) | ||
2858 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
2859 | |||
2860 | link_name = (char *)TLV_DATA(req_tlv_area); | ||
2861 | if (!strcmp(link_name, bc_link_name)) { | ||
2862 | if (bclink_reset_stats()) | ||
2863 | return cfg_reply_error_string("link not found"); | ||
2864 | return cfg_reply_none(); | ||
2865 | } | ||
2866 | |||
2867 | read_lock_bh(&net_lock); | ||
2868 | l_ptr = link_find_link(link_name, &node); | ||
2869 | if (!l_ptr) { | ||
2870 | read_unlock_bh(&net_lock); | ||
2871 | return cfg_reply_error_string("link not found"); | ||
2872 | } | ||
2873 | |||
2874 | node_lock(node); | ||
2875 | link_reset_statistics(l_ptr); | ||
2876 | node_unlock(node); | ||
2877 | read_unlock_bh(&net_lock); | ||
2878 | return cfg_reply_none(); | ||
2879 | } | ||
2880 | |||
2881 | /** | ||
2882 | * percent - convert count to a percentage of total (rounding up or down) | ||
2883 | */ | ||
2884 | |||
2885 | static u32 percent(u32 count, u32 total) | ||
2886 | { | ||
2887 | return (count * 100 + (total / 2)) / total; | ||
2888 | } | ||
2889 | |||
2890 | /** | ||
2891 | * link_stats - print link statistics | ||
2892 | * @name: link name | ||
2893 | * @buf: print buffer area | ||
2894 | * @buf_size: size of print buffer area | ||
2895 | * | ||
2896 | * Returns length of print buffer data string (or 0 if error) | ||
2897 | */ | ||
2898 | |||
2899 | static int link_stats(const char *name, char *buf, const u32 buf_size) | ||
2900 | { | ||
2901 | struct print_buf pb; | ||
2902 | struct link *l_ptr; | ||
2903 | struct node *node; | ||
2904 | char *status; | ||
2905 | u32 profile_total = 0; | ||
2906 | |||
2907 | if (!strcmp(name, bc_link_name)) | ||
2908 | return bclink_stats(buf, buf_size); | ||
2909 | |||
2910 | printbuf_init(&pb, buf, buf_size); | ||
2911 | |||
2912 | read_lock_bh(&net_lock); | ||
2913 | l_ptr = link_find_link(name, &node); | ||
2914 | if (!l_ptr) { | ||
2915 | read_unlock_bh(&net_lock); | ||
2916 | return 0; | ||
2917 | } | ||
2918 | node_lock(node); | ||
2919 | |||
2920 | if (link_is_active(l_ptr)) | ||
2921 | status = "ACTIVE"; | ||
2922 | else if (link_is_up(l_ptr)) | ||
2923 | status = "STANDBY"; | ||
2924 | else | ||
2925 | status = "DEFUNCT"; | ||
2926 | tipc_printf(&pb, "Link <%s>\n" | ||
2927 | " %s MTU:%u Priority:%u Tolerance:%u ms" | ||
2928 | " Window:%u packets\n", | ||
2929 | l_ptr->name, status, link_max_pkt(l_ptr), | ||
2930 | l_ptr->priority, l_ptr->tolerance, l_ptr->queue_limit[0]); | ||
2931 | tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
2932 | l_ptr->next_in_no - l_ptr->stats.recv_info, | ||
2933 | l_ptr->stats.recv_fragments, | ||
2934 | l_ptr->stats.recv_fragmented, | ||
2935 | l_ptr->stats.recv_bundles, | ||
2936 | l_ptr->stats.recv_bundled); | ||
2937 | tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
2938 | l_ptr->next_out_no - l_ptr->stats.sent_info, | ||
2939 | l_ptr->stats.sent_fragments, | ||
2940 | l_ptr->stats.sent_fragmented, | ||
2941 | l_ptr->stats.sent_bundles, | ||
2942 | l_ptr->stats.sent_bundled); | ||
2943 | profile_total = l_ptr->stats.msg_length_counts; | ||
2944 | if (!profile_total) | ||
2945 | profile_total = 1; | ||
2946 | tipc_printf(&pb, " TX profile sample:%u packets average:%u octets\n" | ||
2947 | " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% " | ||
2948 | "-16354:%u%% -32768:%u%% -66000:%u%%\n", | ||
2949 | l_ptr->stats.msg_length_counts, | ||
2950 | l_ptr->stats.msg_lengths_total / profile_total, | ||
2951 | percent(l_ptr->stats.msg_length_profile[0], profile_total), | ||
2952 | percent(l_ptr->stats.msg_length_profile[1], profile_total), | ||
2953 | percent(l_ptr->stats.msg_length_profile[2], profile_total), | ||
2954 | percent(l_ptr->stats.msg_length_profile[3], profile_total), | ||
2955 | percent(l_ptr->stats.msg_length_profile[4], profile_total), | ||
2956 | percent(l_ptr->stats.msg_length_profile[5], profile_total), | ||
2957 | percent(l_ptr->stats.msg_length_profile[6], profile_total)); | ||
2958 | tipc_printf(&pb, " RX states:%u probes:%u naks:%u defs:%u dups:%u\n", | ||
2959 | l_ptr->stats.recv_states, | ||
2960 | l_ptr->stats.recv_probes, | ||
2961 | l_ptr->stats.recv_nacks, | ||
2962 | l_ptr->stats.deferred_recv, | ||
2963 | l_ptr->stats.duplicates); | ||
2964 | tipc_printf(&pb, " TX states:%u probes:%u naks:%u acks:%u dups:%u\n", | ||
2965 | l_ptr->stats.sent_states, | ||
2966 | l_ptr->stats.sent_probes, | ||
2967 | l_ptr->stats.sent_nacks, | ||
2968 | l_ptr->stats.sent_acks, | ||
2969 | l_ptr->stats.retransmitted); | ||
2970 | tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n", | ||
2971 | l_ptr->stats.bearer_congs, | ||
2972 | l_ptr->stats.link_congs, | ||
2973 | l_ptr->stats.max_queue_sz, | ||
2974 | l_ptr->stats.queue_sz_counts | ||
2975 | ? (l_ptr->stats.accu_queue_sz / l_ptr->stats.queue_sz_counts) | ||
2976 | : 0); | ||
2977 | |||
2978 | node_unlock(node); | ||
2979 | read_unlock_bh(&net_lock); | ||
2980 | return printbuf_validate(&pb); | ||
2981 | } | ||
2982 | |||
2983 | #define MAX_LINK_STATS_INFO 2000 | ||
2984 | |||
2985 | struct sk_buff *link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space) | ||
2986 | { | ||
2987 | struct sk_buff *buf; | ||
2988 | struct tlv_desc *rep_tlv; | ||
2989 | int str_len; | ||
2990 | |||
2991 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) | ||
2992 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
2993 | |||
2994 | buf = cfg_reply_alloc(TLV_SPACE(MAX_LINK_STATS_INFO)); | ||
2995 | if (!buf) | ||
2996 | return NULL; | ||
2997 | |||
2998 | rep_tlv = (struct tlv_desc *)buf->data; | ||
2999 | |||
3000 | str_len = link_stats((char *)TLV_DATA(req_tlv_area), | ||
3001 | (char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO); | ||
3002 | if (!str_len) { | ||
3003 | buf_discard(buf); | ||
3004 | return cfg_reply_error_string("link not found"); | ||
3005 | } | ||
3006 | |||
3007 | skb_put(buf, TLV_SPACE(str_len)); | ||
3008 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | ||
3009 | |||
3010 | return buf; | ||
3011 | } | ||
3012 | |||
3013 | #if 0 | ||
3014 | int link_control(const char *name, u32 op, u32 val) | ||
3015 | { | ||
3016 | int res = -EINVAL; | ||
3017 | struct link *l_ptr; | ||
3018 | u32 bearer_id; | ||
3019 | struct node * node; | ||
3020 | u32 a; | ||
3021 | |||
3022 | a = link_name2addr(name, &bearer_id); | ||
3023 | read_lock_bh(&net_lock); | ||
3024 | node = node_find(a); | ||
3025 | if (node) { | ||
3026 | node_lock(node); | ||
3027 | l_ptr = node->links[bearer_id]; | ||
3028 | if (l_ptr) { | ||
3029 | if (op == TIPC_REMOVE_LINK) { | ||
3030 | struct bearer *b_ptr = l_ptr->b_ptr; | ||
3031 | spin_lock_bh(&b_ptr->publ.lock); | ||
3032 | link_delete(l_ptr); | ||
3033 | spin_unlock_bh(&b_ptr->publ.lock); | ||
3034 | } | ||
3035 | if (op == TIPC_CMD_BLOCK_LINK) { | ||
3036 | link_reset(l_ptr); | ||
3037 | l_ptr->blocked = 1; | ||
3038 | } | ||
3039 | if (op == TIPC_CMD_UNBLOCK_LINK) { | ||
3040 | l_ptr->blocked = 0; | ||
3041 | } | ||
3042 | res = TIPC_OK; | ||
3043 | } | ||
3044 | node_unlock(node); | ||
3045 | } | ||
3046 | read_unlock_bh(&net_lock); | ||
3047 | return res; | ||
3048 | } | ||
3049 | #endif | ||
3050 | |||
3051 | /** | ||
3052 | * link_get_max_pkt - get maximum packet size to use when sending to destination | ||
3053 | * @dest: network address of destination node | ||
3054 | * @selector: used to select from set of active links | ||
3055 | * | ||
3056 | * If no active link can be found, uses default maximum packet size. | ||
3057 | */ | ||
3058 | |||
3059 | u32 link_get_max_pkt(u32 dest, u32 selector) | ||
3060 | { | ||
3061 | struct node *n_ptr; | ||
3062 | struct link *l_ptr; | ||
3063 | u32 res = MAX_PKT_DEFAULT; | ||
3064 | |||
3065 | if (dest == tipc_own_addr) | ||
3066 | return MAX_MSG_SIZE; | ||
3067 | |||
3068 | read_lock_bh(&net_lock); | ||
3069 | n_ptr = node_select(dest, selector); | ||
3070 | if (n_ptr) { | ||
3071 | node_lock(n_ptr); | ||
3072 | l_ptr = n_ptr->active_links[selector & 1]; | ||
3073 | if (l_ptr) | ||
3074 | res = link_max_pkt(l_ptr); | ||
3075 | node_unlock(n_ptr); | ||
3076 | } | ||
3077 | read_unlock_bh(&net_lock); | ||
3078 | return res; | ||
3079 | } | ||
3080 | |||
3081 | #if 0 | ||
3082 | static void link_dump_rec_queue(struct link *l_ptr) | ||
3083 | { | ||
3084 | struct sk_buff *crs; | ||
3085 | |||
3086 | if (!l_ptr->oldest_deferred_in) { | ||
3087 | info("Reception queue empty\n"); | ||
3088 | return; | ||
3089 | } | ||
3090 | info("Contents of Reception queue:\n"); | ||
3091 | crs = l_ptr->oldest_deferred_in; | ||
3092 | while (crs) { | ||
3093 | if (crs->data == (void *)0x0000a3a3) { | ||
3094 | info("buffer %x invalid\n", crs); | ||
3095 | return; | ||
3096 | } | ||
3097 | msg_dbg(buf_msg(crs), "In rec queue: \n"); | ||
3098 | crs = crs->next; | ||
3099 | } | ||
3100 | } | ||
3101 | #endif | ||
3102 | |||
3103 | static void link_dump_send_queue(struct link *l_ptr) | ||
3104 | { | ||
3105 | if (l_ptr->next_out) { | ||
3106 | info("\nContents of unsent queue:\n"); | ||
3107 | dbg_print_buf_chain(l_ptr->next_out); | ||
3108 | } | ||
3109 | info("\nContents of send queue:\n"); | ||
3110 | if (l_ptr->first_out) { | ||
3111 | dbg_print_buf_chain(l_ptr->first_out); | ||
3112 | } | ||
3113 | info("Empty send queue\n"); | ||
3114 | } | ||
3115 | |||
3116 | static void link_print(struct link *l_ptr, struct print_buf *buf, | ||
3117 | const char *str) | ||
3118 | { | ||
3119 | tipc_printf(buf, str); | ||
3120 | if (link_reset_reset(l_ptr) || link_reset_unknown(l_ptr)) | ||
3121 | return; | ||
3122 | tipc_printf(buf, "Link %x<%s>:", | ||
3123 | l_ptr->addr, l_ptr->b_ptr->publ.name); | ||
3124 | tipc_printf(buf, ": NXO(%u):", mod(l_ptr->next_out_no)); | ||
3125 | tipc_printf(buf, "NXI(%u):", mod(l_ptr->next_in_no)); | ||
3126 | tipc_printf(buf, "SQUE"); | ||
3127 | if (l_ptr->first_out) { | ||
3128 | tipc_printf(buf, "[%u..", msg_seqno(buf_msg(l_ptr->first_out))); | ||
3129 | if (l_ptr->next_out) | ||
3130 | tipc_printf(buf, "%u..", | ||
3131 | msg_seqno(buf_msg(l_ptr->next_out))); | ||
3132 | tipc_printf(buf, "%u]", | ||
3133 | msg_seqno(buf_msg | ||
3134 | (l_ptr->last_out)), l_ptr->out_queue_size); | ||
3135 | if ((mod(msg_seqno(buf_msg(l_ptr->last_out)) - | ||
3136 | msg_seqno(buf_msg(l_ptr->first_out))) | ||
3137 | != (l_ptr->out_queue_size - 1)) | ||
3138 | || (l_ptr->last_out->next != 0)) { | ||
3139 | tipc_printf(buf, "\nSend queue inconsistency\n"); | ||
3140 | tipc_printf(buf, "first_out= %x ", l_ptr->first_out); | ||
3141 | tipc_printf(buf, "next_out= %x ", l_ptr->next_out); | ||
3142 | tipc_printf(buf, "last_out= %x ", l_ptr->last_out); | ||
3143 | link_dump_send_queue(l_ptr); | ||
3144 | } | ||
3145 | } else | ||
3146 | tipc_printf(buf, "[]"); | ||
3147 | tipc_printf(buf, "SQSIZ(%u)", l_ptr->out_queue_size); | ||
3148 | if (l_ptr->oldest_deferred_in) { | ||
3149 | u32 o = msg_seqno(buf_msg(l_ptr->oldest_deferred_in)); | ||
3150 | u32 n = msg_seqno(buf_msg(l_ptr->newest_deferred_in)); | ||
3151 | tipc_printf(buf, ":RQUE[%u..%u]", o, n); | ||
3152 | if (l_ptr->deferred_inqueue_sz != mod((n + 1) - o)) { | ||
3153 | tipc_printf(buf, ":RQSIZ(%u)", | ||
3154 | l_ptr->deferred_inqueue_sz); | ||
3155 | } | ||
3156 | } | ||
3157 | if (link_working_unknown(l_ptr)) | ||
3158 | tipc_printf(buf, ":WU"); | ||
3159 | if (link_reset_reset(l_ptr)) | ||
3160 | tipc_printf(buf, ":RR"); | ||
3161 | if (link_reset_unknown(l_ptr)) | ||
3162 | tipc_printf(buf, ":RU"); | ||
3163 | if (link_working_working(l_ptr)) | ||
3164 | tipc_printf(buf, ":WW"); | ||
3165 | tipc_printf(buf, "\n"); | ||
3166 | } | ||
3167 | |||
diff --git a/net/tipc/link.h b/net/tipc/link.h new file mode 100644 index 000000000000..c2553f073757 --- /dev/null +++ b/net/tipc/link.h | |||
@@ -0,0 +1,296 @@ | |||
1 | /* | ||
2 | * net/tipc/link.h: Include file for TIPC link code | ||
3 | * | ||
4 | * Copyright (c) 1995-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_LINK_H | ||
38 | #define _TIPC_LINK_H | ||
39 | |||
40 | #include "dbg.h" | ||
41 | #include "msg.h" | ||
42 | #include "bearer.h" | ||
43 | #include "node.h" | ||
44 | |||
45 | #define PUSH_FAILED 1 | ||
46 | #define PUSH_FINISHED 2 | ||
47 | |||
48 | /* | ||
49 | * Link states | ||
50 | */ | ||
51 | |||
52 | #define WORKING_WORKING 560810u | ||
53 | #define WORKING_UNKNOWN 560811u | ||
54 | #define RESET_UNKNOWN 560812u | ||
55 | #define RESET_RESET 560813u | ||
56 | |||
57 | /* | ||
58 | * Starting value for maximum packet size negotiation on unicast links | ||
59 | * (unless bearer MTU is less) | ||
60 | */ | ||
61 | |||
62 | #define MAX_PKT_DEFAULT 1500 | ||
63 | |||
64 | /** | ||
65 | * struct link - TIPC link data structure | ||
66 | * @addr: network address of link's peer node | ||
67 | * @name: link name character string | ||
68 | * @media_addr: media address to use when sending messages over link | ||
69 | * @timer: link timer | ||
70 | * @owner: pointer to peer node | ||
71 | * @link_list: adjacent links in bearer's list of links | ||
72 | * @started: indicates if link has been started | ||
73 | * @checkpoint: reference point for triggering link continuity checking | ||
74 | * @peer_session: link session # being used by peer end of link | ||
75 | * @peer_bearer_id: bearer id used by link's peer endpoint | ||
76 | * @b_ptr: pointer to bearer used by link | ||
77 | * @tolerance: minimum link continuity loss needed to reset link [in ms] | ||
78 | * @continuity_interval: link continuity testing interval [in ms] | ||
79 | * @abort_limit: # of unacknowledged continuity probes needed to reset link | ||
80 | * @state: current state of link FSM | ||
81 | * @blocked: indicates if link has been administratively blocked | ||
82 | * @fsm_msg_cnt: # of protocol messages link FSM has sent in current state | ||
83 | * @proto_msg: template for control messages generated by link | ||
84 | * @pmsg: convenience pointer to "proto_msg" field | ||
85 | * @priority: current link priority | ||
86 | * @queue_limit: outbound message queue congestion thresholds (indexed by user) | ||
87 | * @exp_msg_count: # of tunnelled messages expected during link changeover | ||
88 | * @reset_checkpoint: seq # of last acknowledged message at time of link reset | ||
89 | * @max_pkt: current maximum packet size for this link | ||
90 | * @max_pkt_target: desired maximum packet size for this link | ||
91 | * @max_pkt_probes: # of probes based on current (max_pkt, max_pkt_target) | ||
92 | * @out_queue_size: # of messages in outbound message queue | ||
93 | * @first_out: ptr to first outbound message in queue | ||
94 | * @last_out: ptr to last outbound message in queue | ||
95 | * @next_out_no: next sequence number to use for outbound messages | ||
96 | * @last_retransmitted: sequence number of most recently retransmitted message | ||
97 | * @stale_count: # of identical retransmit requests made by peer | ||
98 | * @next_in_no: next sequence number to expect for inbound messages | ||
99 | * @deferred_inqueue_sz: # of messages in inbound message queue | ||
100 | * @oldest_deferred_in: ptr to first inbound message in queue | ||
101 | * @newest_deferred_in: ptr to last inbound message in queue | ||
102 | * @unacked_window: # of inbound messages rx'd without ack'ing back to peer | ||
103 | * @proto_msg_queue: ptr to (single) outbound control message | ||
104 | * @retransm_queue_size: number of messages to retransmit | ||
105 | * @retransm_queue_head: sequence number of first message to retransmit | ||
106 | * @next_out: ptr to first unsent outbound message in queue | ||
107 | * @waiting_ports: linked list of ports waiting for link congestion to abate | ||
108 | * @long_msg_seq_no: next identifier to use for outbound fragmented messages | ||
109 | * @defragm_buf: list of partially reassembled inbound message fragments | ||
110 | * @stats: collects statistics regarding link activity | ||
111 | * @print_buf: print buffer used to log link activity | ||
112 | */ | ||
113 | |||
114 | struct link { | ||
115 | u32 addr; | ||
116 | char name[TIPC_MAX_LINK_NAME]; | ||
117 | struct tipc_media_addr media_addr; | ||
118 | struct timer_list timer; | ||
119 | struct node *owner; | ||
120 | struct list_head link_list; | ||
121 | |||
122 | /* Management and link supervision data */ | ||
123 | int started; | ||
124 | u32 checkpoint; | ||
125 | u32 peer_session; | ||
126 | u32 peer_bearer_id; | ||
127 | struct bearer *b_ptr; | ||
128 | u32 tolerance; | ||
129 | u32 continuity_interval; | ||
130 | u32 abort_limit; | ||
131 | int state; | ||
132 | int blocked; | ||
133 | u32 fsm_msg_cnt; | ||
134 | struct { | ||
135 | unchar hdr[INT_H_SIZE]; | ||
136 | unchar body[TIPC_MAX_IF_NAME]; | ||
137 | } proto_msg; | ||
138 | struct tipc_msg *pmsg; | ||
139 | u32 priority; | ||
140 | u32 queue_limit[15]; /* queue_limit[0]==window limit */ | ||
141 | |||
142 | /* Changeover */ | ||
143 | u32 exp_msg_count; | ||
144 | u32 reset_checkpoint; | ||
145 | |||
146 | /* Max packet negotiation */ | ||
147 | u32 max_pkt; | ||
148 | u32 max_pkt_target; | ||
149 | u32 max_pkt_probes; | ||
150 | |||
151 | /* Sending */ | ||
152 | u32 out_queue_size; | ||
153 | struct sk_buff *first_out; | ||
154 | struct sk_buff *last_out; | ||
155 | u32 next_out_no; | ||
156 | u32 last_retransmitted; | ||
157 | u32 stale_count; | ||
158 | |||
159 | /* Reception */ | ||
160 | u32 next_in_no; | ||
161 | u32 deferred_inqueue_sz; | ||
162 | struct sk_buff *oldest_deferred_in; | ||
163 | struct sk_buff *newest_deferred_in; | ||
164 | u32 unacked_window; | ||
165 | |||
166 | /* Congestion handling */ | ||
167 | struct sk_buff *proto_msg_queue; | ||
168 | u32 retransm_queue_size; | ||
169 | u32 retransm_queue_head; | ||
170 | struct sk_buff *next_out; | ||
171 | struct list_head waiting_ports; | ||
172 | |||
173 | /* Fragmentation/defragmentation */ | ||
174 | u32 long_msg_seq_no; | ||
175 | struct sk_buff *defragm_buf; | ||
176 | |||
177 | /* Statistics */ | ||
178 | struct { | ||
179 | u32 sent_info; /* used in counting # sent packets */ | ||
180 | u32 recv_info; /* used in counting # recv'd packets */ | ||
181 | u32 sent_states; | ||
182 | u32 recv_states; | ||
183 | u32 sent_probes; | ||
184 | u32 recv_probes; | ||
185 | u32 sent_nacks; | ||
186 | u32 recv_nacks; | ||
187 | u32 sent_acks; | ||
188 | u32 sent_bundled; | ||
189 | u32 sent_bundles; | ||
190 | u32 recv_bundled; | ||
191 | u32 recv_bundles; | ||
192 | u32 retransmitted; | ||
193 | u32 sent_fragmented; | ||
194 | u32 sent_fragments; | ||
195 | u32 recv_fragmented; | ||
196 | u32 recv_fragments; | ||
197 | u32 link_congs; /* # port sends blocked by congestion */ | ||
198 | u32 bearer_congs; | ||
199 | u32 deferred_recv; | ||
200 | u32 duplicates; | ||
201 | |||
202 | /* for statistical profiling of send queue size */ | ||
203 | |||
204 | u32 max_queue_sz; | ||
205 | u32 accu_queue_sz; | ||
206 | u32 queue_sz_counts; | ||
207 | |||
208 | /* for statistical profiling of message lengths */ | ||
209 | |||
210 | u32 msg_length_counts; | ||
211 | u32 msg_lengths_total; | ||
212 | u32 msg_length_profile[7]; | ||
213 | #if 0 | ||
214 | u32 sent_tunneled; | ||
215 | u32 recv_tunneled; | ||
216 | #endif | ||
217 | } stats; | ||
218 | |||
219 | struct print_buf print_buf; | ||
220 | }; | ||
221 | |||
222 | struct port; | ||
223 | |||
224 | struct link *link_create(struct bearer *b_ptr, const u32 peer, | ||
225 | const struct tipc_media_addr *media_addr); | ||
226 | void link_delete(struct link *l_ptr); | ||
227 | void link_changeover(struct link *l_ptr); | ||
228 | void link_send_duplicate(struct link *l_ptr, struct link *dest); | ||
229 | void link_reset_fragments(struct link *l_ptr); | ||
230 | int link_is_up(struct link *l_ptr); | ||
231 | int link_is_active(struct link *l_ptr); | ||
232 | void link_start(struct link *l_ptr); | ||
233 | u32 link_push_packet(struct link *l_ptr); | ||
234 | void link_stop(struct link *l_ptr); | ||
235 | struct sk_buff *link_cmd_config(const void *req_tlv_area, int req_tlv_space, u16 cmd); | ||
236 | struct sk_buff *link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space); | ||
237 | struct sk_buff *link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space); | ||
238 | void link_reset(struct link *l_ptr); | ||
239 | int link_send(struct sk_buff *buf, u32 dest, u32 selector); | ||
240 | int link_send_buf(struct link *l_ptr, struct sk_buff *buf); | ||
241 | u32 link_get_max_pkt(u32 dest,u32 selector); | ||
242 | int link_send_sections_fast(struct port* sender, | ||
243 | struct iovec const *msg_sect, | ||
244 | const u32 num_sect, | ||
245 | u32 destnode); | ||
246 | |||
247 | int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf); | ||
248 | void link_tunnel(struct link *l_ptr, struct tipc_msg *tnl_hdr, | ||
249 | struct tipc_msg *msg, u32 selector); | ||
250 | void link_recv_bundle(struct sk_buff *buf); | ||
251 | int link_recv_fragment(struct sk_buff **pending, | ||
252 | struct sk_buff **fb, | ||
253 | struct tipc_msg **msg); | ||
254 | void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int prob, u32 gap, | ||
255 | u32 tolerance, u32 priority, u32 acked_mtu); | ||
256 | void link_push_queue(struct link *l_ptr); | ||
257 | u32 link_defer_pkt(struct sk_buff **head, struct sk_buff **tail, | ||
258 | struct sk_buff *buf); | ||
259 | void link_wakeup_ports(struct link *l_ptr, int all); | ||
260 | void link_set_queue_limits(struct link *l_ptr, u32 window); | ||
261 | void link_retransmit(struct link *l_ptr, struct sk_buff *start, u32 retransmits); | ||
262 | |||
263 | /* | ||
264 | * Link sequence number manipulation routines (uses modulo 2**16 arithmetic) | ||
265 | */ | ||
266 | |||
267 | static inline u32 mod(u32 x) | ||
268 | { | ||
269 | return x & 0xffffu; | ||
270 | } | ||
271 | |||
272 | static inline int between(u32 lower, u32 upper, u32 n) | ||
273 | { | ||
274 | if ((lower < n) && (n < upper)) | ||
275 | return 1; | ||
276 | if ((upper < lower) && ((n > lower) || (n < upper))) | ||
277 | return 1; | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static inline int less_eq(u32 left, u32 right) | ||
282 | { | ||
283 | return (mod(right - left) < 32768u); | ||
284 | } | ||
285 | |||
286 | static inline int less(u32 left, u32 right) | ||
287 | { | ||
288 | return (less_eq(left, right) && (mod(right) != mod(left))); | ||
289 | } | ||
290 | |||
291 | static inline u32 lesser(u32 left, u32 right) | ||
292 | { | ||
293 | return less_eq(left, right) ? left : right; | ||
294 | } | ||
295 | |||
296 | #endif | ||
diff --git a/net/tipc/msg.c b/net/tipc/msg.c new file mode 100644 index 000000000000..03dbc55cb04c --- /dev/null +++ b/net/tipc/msg.c | |||
@@ -0,0 +1,334 @@ | |||
1 | /* | ||
2 | * net/tipc/msg.c: TIPC message header routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "addr.h" | ||
39 | #include "dbg.h" | ||
40 | #include "msg.h" | ||
41 | #include "bearer.h" | ||
42 | |||
43 | |||
44 | void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) | ||
45 | { | ||
46 | memcpy(&((int *)m)[5], a, sizeof(*a)); | ||
47 | } | ||
48 | |||
49 | void msg_get_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) | ||
50 | { | ||
51 | memcpy(a, &((int*)m)[5], sizeof(*a)); | ||
52 | } | ||
53 | |||
54 | |||
55 | void msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str) | ||
56 | { | ||
57 | u32 usr = msg_user(msg); | ||
58 | tipc_printf(buf, str); | ||
59 | |||
60 | switch (usr) { | ||
61 | case MSG_BUNDLER: | ||
62 | tipc_printf(buf, "BNDL::"); | ||
63 | tipc_printf(buf, "MSGS(%u):", msg_msgcnt(msg)); | ||
64 | break; | ||
65 | case BCAST_PROTOCOL: | ||
66 | tipc_printf(buf, "BCASTP::"); | ||
67 | break; | ||
68 | case MSG_FRAGMENTER: | ||
69 | tipc_printf(buf, "FRAGM::"); | ||
70 | switch (msg_type(msg)) { | ||
71 | case FIRST_FRAGMENT: | ||
72 | tipc_printf(buf, "FIRST:"); | ||
73 | break; | ||
74 | case FRAGMENT: | ||
75 | tipc_printf(buf, "BODY:"); | ||
76 | break; | ||
77 | case LAST_FRAGMENT: | ||
78 | tipc_printf(buf, "LAST:"); | ||
79 | break; | ||
80 | default: | ||
81 | tipc_printf(buf, "UNKNOWN:%x",msg_type(msg)); | ||
82 | |||
83 | } | ||
84 | tipc_printf(buf, "NO(%u/%u):",msg_long_msgno(msg), | ||
85 | msg_fragm_no(msg)); | ||
86 | break; | ||
87 | case DATA_LOW: | ||
88 | case DATA_MEDIUM: | ||
89 | case DATA_HIGH: | ||
90 | case DATA_CRITICAL: | ||
91 | tipc_printf(buf, "DAT%u:", msg_user(msg)); | ||
92 | if (msg_short(msg)) { | ||
93 | tipc_printf(buf, "CON:"); | ||
94 | break; | ||
95 | } | ||
96 | switch (msg_type(msg)) { | ||
97 | case TIPC_CONN_MSG: | ||
98 | tipc_printf(buf, "CON:"); | ||
99 | break; | ||
100 | case TIPC_MCAST_MSG: | ||
101 | tipc_printf(buf, "MCST:"); | ||
102 | break; | ||
103 | case TIPC_NAMED_MSG: | ||
104 | tipc_printf(buf, "NAM:"); | ||
105 | break; | ||
106 | case TIPC_DIRECT_MSG: | ||
107 | tipc_printf(buf, "DIR:"); | ||
108 | break; | ||
109 | default: | ||
110 | tipc_printf(buf, "UNKNOWN TYPE %u",msg_type(msg)); | ||
111 | } | ||
112 | if (msg_routed(msg) && !msg_non_seq(msg)) | ||
113 | tipc_printf(buf, "ROUT:"); | ||
114 | if (msg_reroute_cnt(msg)) | ||
115 | tipc_printf(buf, "REROUTED(%u):", | ||
116 | msg_reroute_cnt(msg)); | ||
117 | break; | ||
118 | case NAME_DISTRIBUTOR: | ||
119 | tipc_printf(buf, "NMD::"); | ||
120 | switch (msg_type(msg)) { | ||
121 | case PUBLICATION: | ||
122 | tipc_printf(buf, "PUBL(%u):", (msg_size(msg) - msg_hdr_sz(msg)) / 20); /* Items */ | ||
123 | break; | ||
124 | case WITHDRAWAL: | ||
125 | tipc_printf(buf, "WDRW:"); | ||
126 | break; | ||
127 | default: | ||
128 | tipc_printf(buf, "UNKNOWN:%x",msg_type(msg)); | ||
129 | } | ||
130 | if (msg_routed(msg)) | ||
131 | tipc_printf(buf, "ROUT:"); | ||
132 | if (msg_reroute_cnt(msg)) | ||
133 | tipc_printf(buf, "REROUTED(%u):", | ||
134 | msg_reroute_cnt(msg)); | ||
135 | break; | ||
136 | case CONN_MANAGER: | ||
137 | tipc_printf(buf, "CONN_MNG:"); | ||
138 | switch (msg_type(msg)) { | ||
139 | case CONN_PROBE: | ||
140 | tipc_printf(buf, "PROBE:"); | ||
141 | break; | ||
142 | case CONN_PROBE_REPLY: | ||
143 | tipc_printf(buf, "PROBE_REPLY:"); | ||
144 | break; | ||
145 | case CONN_ACK: | ||
146 | tipc_printf(buf, "CONN_ACK:"); | ||
147 | tipc_printf(buf, "ACK(%u):",msg_msgcnt(msg)); | ||
148 | break; | ||
149 | default: | ||
150 | tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); | ||
151 | } | ||
152 | if (msg_routed(msg)) | ||
153 | tipc_printf(buf, "ROUT:"); | ||
154 | if (msg_reroute_cnt(msg)) | ||
155 | tipc_printf(buf, "REROUTED(%u):",msg_reroute_cnt(msg)); | ||
156 | break; | ||
157 | case LINK_PROTOCOL: | ||
158 | tipc_printf(buf, "PROT:TIM(%u):",msg_timestamp(msg)); | ||
159 | switch (msg_type(msg)) { | ||
160 | case STATE_MSG: | ||
161 | tipc_printf(buf, "STATE:"); | ||
162 | tipc_printf(buf, "%s:",msg_probe(msg) ? "PRB" :""); | ||
163 | tipc_printf(buf, "NXS(%u):",msg_next_sent(msg)); | ||
164 | tipc_printf(buf, "GAP(%u):",msg_seq_gap(msg)); | ||
165 | tipc_printf(buf, "LSTBC(%u):",msg_last_bcast(msg)); | ||
166 | break; | ||
167 | case RESET_MSG: | ||
168 | tipc_printf(buf, "RESET:"); | ||
169 | if (msg_size(msg) != msg_hdr_sz(msg)) | ||
170 | tipc_printf(buf, "BEAR:%s:",msg_data(msg)); | ||
171 | break; | ||
172 | case ACTIVATE_MSG: | ||
173 | tipc_printf(buf, "ACTIVATE:"); | ||
174 | break; | ||
175 | default: | ||
176 | tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); | ||
177 | } | ||
178 | tipc_printf(buf, "PLANE(%c):",msg_net_plane(msg)); | ||
179 | tipc_printf(buf, "SESS(%u):",msg_session(msg)); | ||
180 | break; | ||
181 | case CHANGEOVER_PROTOCOL: | ||
182 | tipc_printf(buf, "TUNL:"); | ||
183 | switch (msg_type(msg)) { | ||
184 | case DUPLICATE_MSG: | ||
185 | tipc_printf(buf, "DUPL:"); | ||
186 | break; | ||
187 | case ORIGINAL_MSG: | ||
188 | tipc_printf(buf, "ORIG:"); | ||
189 | tipc_printf(buf, "EXP(%u)",msg_msgcnt(msg)); | ||
190 | break; | ||
191 | default: | ||
192 | tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); | ||
193 | } | ||
194 | break; | ||
195 | case ROUTE_DISTRIBUTOR: | ||
196 | tipc_printf(buf, "ROUTING_MNG:"); | ||
197 | switch (msg_type(msg)) { | ||
198 | case EXT_ROUTING_TABLE: | ||
199 | tipc_printf(buf, "EXT_TBL:"); | ||
200 | tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); | ||
201 | break; | ||
202 | case LOCAL_ROUTING_TABLE: | ||
203 | tipc_printf(buf, "LOCAL_TBL:"); | ||
204 | tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); | ||
205 | break; | ||
206 | case SLAVE_ROUTING_TABLE: | ||
207 | tipc_printf(buf, "DP_TBL:"); | ||
208 | tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); | ||
209 | break; | ||
210 | case ROUTE_ADDITION: | ||
211 | tipc_printf(buf, "ADD:"); | ||
212 | tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); | ||
213 | break; | ||
214 | case ROUTE_REMOVAL: | ||
215 | tipc_printf(buf, "REMOVE:"); | ||
216 | tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); | ||
217 | break; | ||
218 | default: | ||
219 | tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); | ||
220 | } | ||
221 | break; | ||
222 | case LINK_CONFIG: | ||
223 | tipc_printf(buf, "CFG:"); | ||
224 | switch (msg_type(msg)) { | ||
225 | case DSC_REQ_MSG: | ||
226 | tipc_printf(buf, "DSC_REQ:"); | ||
227 | break; | ||
228 | case DSC_RESP_MSG: | ||
229 | tipc_printf(buf, "DSC_RESP:"); | ||
230 | break; | ||
231 | default: | ||
232 | tipc_printf(buf, "UNKNOWN TYPE:%x:",msg_type(msg)); | ||
233 | break; | ||
234 | } | ||
235 | break; | ||
236 | default: | ||
237 | tipc_printf(buf, "UNKNOWN USER:"); | ||
238 | } | ||
239 | |||
240 | switch (usr) { | ||
241 | case CONN_MANAGER: | ||
242 | case NAME_DISTRIBUTOR: | ||
243 | case DATA_LOW: | ||
244 | case DATA_MEDIUM: | ||
245 | case DATA_HIGH: | ||
246 | case DATA_CRITICAL: | ||
247 | if (msg_short(msg)) | ||
248 | break; /* No error */ | ||
249 | switch (msg_errcode(msg)) { | ||
250 | case TIPC_OK: | ||
251 | break; | ||
252 | case TIPC_ERR_NO_NAME: | ||
253 | tipc_printf(buf, "NO_NAME:"); | ||
254 | break; | ||
255 | case TIPC_ERR_NO_PORT: | ||
256 | tipc_printf(buf, "NO_PORT:"); | ||
257 | break; | ||
258 | case TIPC_ERR_NO_NODE: | ||
259 | tipc_printf(buf, "NO_PROC:"); | ||
260 | break; | ||
261 | case TIPC_ERR_OVERLOAD: | ||
262 | tipc_printf(buf, "OVERLOAD:"); | ||
263 | break; | ||
264 | case TIPC_CONN_SHUTDOWN: | ||
265 | tipc_printf(buf, "SHUTDOWN:"); | ||
266 | break; | ||
267 | default: | ||
268 | tipc_printf(buf, "UNKNOWN ERROR(%x):", | ||
269 | msg_errcode(msg)); | ||
270 | } | ||
271 | default:{} | ||
272 | } | ||
273 | |||
274 | tipc_printf(buf, "HZ(%u):", msg_hdr_sz(msg)); | ||
275 | tipc_printf(buf, "SZ(%u):", msg_size(msg)); | ||
276 | tipc_printf(buf, "SQNO(%u):", msg_seqno(msg)); | ||
277 | |||
278 | if (msg_non_seq(msg)) | ||
279 | tipc_printf(buf, "NOSEQ:"); | ||
280 | else { | ||
281 | tipc_printf(buf, "ACK(%u):", msg_ack(msg)); | ||
282 | } | ||
283 | tipc_printf(buf, "BACK(%u):", msg_bcast_ack(msg)); | ||
284 | tipc_printf(buf, "PRND(%x)", msg_prevnode(msg)); | ||
285 | |||
286 | if (msg_isdata(msg)) { | ||
287 | if (msg_named(msg)) { | ||
288 | tipc_printf(buf, "NTYP(%u):", msg_nametype(msg)); | ||
289 | tipc_printf(buf, "NINST(%u)", msg_nameinst(msg)); | ||
290 | } | ||
291 | } | ||
292 | |||
293 | if ((usr != LINK_PROTOCOL) && (usr != LINK_CONFIG) && | ||
294 | (usr != MSG_BUNDLER)) { | ||
295 | if (!msg_short(msg)) { | ||
296 | tipc_printf(buf, ":ORIG(%x:%u):", | ||
297 | msg_orignode(msg), msg_origport(msg)); | ||
298 | tipc_printf(buf, ":DEST(%x:%u):", | ||
299 | msg_destnode(msg), msg_destport(msg)); | ||
300 | } else { | ||
301 | tipc_printf(buf, ":OPRT(%u):", msg_origport(msg)); | ||
302 | tipc_printf(buf, ":DPRT(%u):", msg_destport(msg)); | ||
303 | } | ||
304 | if (msg_routed(msg) && !msg_non_seq(msg)) | ||
305 | tipc_printf(buf, ":TSEQN(%u)", msg_transp_seqno(msg)); | ||
306 | } | ||
307 | if (msg_user(msg) == NAME_DISTRIBUTOR) { | ||
308 | tipc_printf(buf, ":ONOD(%x):", msg_orignode(msg)); | ||
309 | tipc_printf(buf, ":DNOD(%x):", msg_destnode(msg)); | ||
310 | if (msg_routed(msg)) { | ||
311 | tipc_printf(buf, ":CSEQN(%u)", msg_transp_seqno(msg)); | ||
312 | } | ||
313 | } | ||
314 | |||
315 | if (msg_user(msg) == LINK_CONFIG) { | ||
316 | u32* raw = (u32*)msg; | ||
317 | struct tipc_media_addr* orig = (struct tipc_media_addr*)&raw[5]; | ||
318 | tipc_printf(buf, ":REQL(%u):", msg_req_links(msg)); | ||
319 | tipc_printf(buf, ":DDOM(%x):", msg_dest_domain(msg)); | ||
320 | tipc_printf(buf, ":NETID(%u):", msg_bc_netid(msg)); | ||
321 | media_addr_printf(buf, orig); | ||
322 | } | ||
323 | if (msg_user(msg) == BCAST_PROTOCOL) { | ||
324 | tipc_printf(buf, "BCNACK:AFTER(%u):", msg_bcgap_after(msg)); | ||
325 | tipc_printf(buf, "TO(%u):", msg_bcgap_to(msg)); | ||
326 | } | ||
327 | tipc_printf(buf, "\n"); | ||
328 | if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) { | ||
329 | msg_print(buf,msg_get_wrapped(msg)," /"); | ||
330 | } | ||
331 | if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) { | ||
332 | msg_print(buf,msg_get_wrapped(msg)," /"); | ||
333 | } | ||
334 | } | ||
diff --git a/net/tipc/msg.h b/net/tipc/msg.h new file mode 100644 index 000000000000..662c81862a0c --- /dev/null +++ b/net/tipc/msg.h | |||
@@ -0,0 +1,818 @@ | |||
1 | /* | ||
2 | * net/tipc/msg.h: Include file for TIPC message header routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_MSG_H | ||
38 | #define _TIPC_MSG_H | ||
39 | |||
40 | #include <net/tipc/tipc_msg.h> | ||
41 | |||
42 | #define TIPC_VERSION 2 | ||
43 | #define DATA_LOW TIPC_LOW_IMPORTANCE | ||
44 | #define DATA_MEDIUM TIPC_MEDIUM_IMPORTANCE | ||
45 | #define DATA_HIGH TIPC_HIGH_IMPORTANCE | ||
46 | #define DATA_CRITICAL TIPC_CRITICAL_IMPORTANCE | ||
47 | #define SHORT_H_SIZE 24 /* Connected,in cluster */ | ||
48 | #define DIR_MSG_H_SIZE 32 /* Directly addressed messages */ | ||
49 | #define CONN_MSG_H_SIZE 36 /* Routed connected msgs*/ | ||
50 | #define LONG_H_SIZE 40 /* Named Messages */ | ||
51 | #define MCAST_H_SIZE 44 /* Multicast messages */ | ||
52 | #define MAX_H_SIZE 60 /* Inclusive full options */ | ||
53 | #define MAX_MSG_SIZE (MAX_H_SIZE + TIPC_MAX_USER_MSG_SIZE) | ||
54 | #define LINK_CONFIG 13 | ||
55 | |||
56 | |||
57 | /* | ||
58 | TIPC user data message header format, version 2 | ||
59 | |||
60 | - Fundamental definitions available to privileged TIPC users | ||
61 | are located in tipc_msg.h. | ||
62 | - Remaining definitions available to TIPC internal users appear below. | ||
63 | */ | ||
64 | |||
65 | |||
66 | static inline void msg_set_word(struct tipc_msg *m, u32 w, u32 val) | ||
67 | { | ||
68 | m->hdr[w] = htonl(val); | ||
69 | } | ||
70 | |||
71 | static inline void msg_set_bits(struct tipc_msg *m, u32 w, | ||
72 | u32 pos, u32 mask, u32 val) | ||
73 | { | ||
74 | u32 word = msg_word(m,w) & ~(mask << pos); | ||
75 | msg_set_word(m, w, (word |= (val << pos))); | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * Word 0 | ||
80 | */ | ||
81 | |||
82 | static inline u32 msg_version(struct tipc_msg *m) | ||
83 | { | ||
84 | return msg_bits(m, 0, 29, 7); | ||
85 | } | ||
86 | |||
87 | static inline void msg_set_version(struct tipc_msg *m) | ||
88 | { | ||
89 | msg_set_bits(m, 0, 29, 0xf, TIPC_VERSION); | ||
90 | } | ||
91 | |||
92 | static inline u32 msg_user(struct tipc_msg *m) | ||
93 | { | ||
94 | return msg_bits(m, 0, 25, 0xf); | ||
95 | } | ||
96 | |||
97 | static inline u32 msg_isdata(struct tipc_msg *m) | ||
98 | { | ||
99 | return (msg_user(m) <= DATA_CRITICAL); | ||
100 | } | ||
101 | |||
102 | static inline void msg_set_user(struct tipc_msg *m, u32 n) | ||
103 | { | ||
104 | msg_set_bits(m, 0, 25, 0xf, n); | ||
105 | } | ||
106 | |||
107 | static inline void msg_set_importance(struct tipc_msg *m, u32 i) | ||
108 | { | ||
109 | msg_set_user(m, i); | ||
110 | } | ||
111 | |||
112 | static inline void msg_set_hdr_sz(struct tipc_msg *m,u32 n) | ||
113 | { | ||
114 | msg_set_bits(m, 0, 21, 0xf, n>>2); | ||
115 | } | ||
116 | |||
117 | static inline int msg_non_seq(struct tipc_msg *m) | ||
118 | { | ||
119 | return msg_bits(m, 0, 20, 1); | ||
120 | } | ||
121 | |||
122 | static inline void msg_set_non_seq(struct tipc_msg *m) | ||
123 | { | ||
124 | msg_set_bits(m, 0, 20, 1, 1); | ||
125 | } | ||
126 | |||
127 | static inline int msg_dest_droppable(struct tipc_msg *m) | ||
128 | { | ||
129 | return msg_bits(m, 0, 19, 1); | ||
130 | } | ||
131 | |||
132 | static inline void msg_set_dest_droppable(struct tipc_msg *m, u32 d) | ||
133 | { | ||
134 | msg_set_bits(m, 0, 19, 1, d); | ||
135 | } | ||
136 | |||
137 | static inline int msg_src_droppable(struct tipc_msg *m) | ||
138 | { | ||
139 | return msg_bits(m, 0, 18, 1); | ||
140 | } | ||
141 | |||
142 | static inline void msg_set_src_droppable(struct tipc_msg *m, u32 d) | ||
143 | { | ||
144 | msg_set_bits(m, 0, 18, 1, d); | ||
145 | } | ||
146 | |||
147 | static inline void msg_set_size(struct tipc_msg *m, u32 sz) | ||
148 | { | ||
149 | m->hdr[0] = htonl((msg_word(m, 0) & ~0x1ffff) | sz); | ||
150 | } | ||
151 | |||
152 | |||
153 | /* | ||
154 | * Word 1 | ||
155 | */ | ||
156 | |||
157 | static inline void msg_set_type(struct tipc_msg *m, u32 n) | ||
158 | { | ||
159 | msg_set_bits(m, 1, 29, 0x7, n); | ||
160 | } | ||
161 | |||
162 | static inline void msg_set_errcode(struct tipc_msg *m, u32 err) | ||
163 | { | ||
164 | msg_set_bits(m, 1, 25, 0xf, err); | ||
165 | } | ||
166 | |||
167 | static inline u32 msg_reroute_cnt(struct tipc_msg *m) | ||
168 | { | ||
169 | return msg_bits(m, 1, 21, 0xf); | ||
170 | } | ||
171 | |||
172 | static inline void msg_incr_reroute_cnt(struct tipc_msg *m) | ||
173 | { | ||
174 | msg_set_bits(m, 1, 21, 0xf, msg_reroute_cnt(m) + 1); | ||
175 | } | ||
176 | |||
177 | static inline void msg_reset_reroute_cnt(struct tipc_msg *m) | ||
178 | { | ||
179 | msg_set_bits(m, 1, 21, 0xf, 0); | ||
180 | } | ||
181 | |||
182 | static inline u32 msg_lookup_scope(struct tipc_msg *m) | ||
183 | { | ||
184 | return msg_bits(m, 1, 19, 0x3); | ||
185 | } | ||
186 | |||
187 | static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n) | ||
188 | { | ||
189 | msg_set_bits(m, 1, 19, 0x3, n); | ||
190 | } | ||
191 | |||
192 | static inline void msg_set_options(struct tipc_msg *m, const char *opt, u32 sz) | ||
193 | { | ||
194 | u32 hsz = msg_hdr_sz(m); | ||
195 | char *to = (char *)&m->hdr[hsz/4]; | ||
196 | |||
197 | if ((hsz < DIR_MSG_H_SIZE) || ((hsz + sz) > MAX_H_SIZE)) | ||
198 | return; | ||
199 | msg_set_bits(m, 1, 16, 0x7, (hsz - 28)/4); | ||
200 | msg_set_hdr_sz(m, hsz + sz); | ||
201 | memcpy(to, opt, sz); | ||
202 | } | ||
203 | |||
204 | static inline u32 msg_bcast_ack(struct tipc_msg *m) | ||
205 | { | ||
206 | return msg_bits(m, 1, 0, 0xffff); | ||
207 | } | ||
208 | |||
209 | static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n) | ||
210 | { | ||
211 | msg_set_bits(m, 1, 0, 0xffff, n); | ||
212 | } | ||
213 | |||
214 | |||
215 | /* | ||
216 | * Word 2 | ||
217 | */ | ||
218 | |||
219 | static inline u32 msg_ack(struct tipc_msg *m) | ||
220 | { | ||
221 | return msg_bits(m, 2, 16, 0xffff); | ||
222 | } | ||
223 | |||
224 | static inline void msg_set_ack(struct tipc_msg *m, u32 n) | ||
225 | { | ||
226 | msg_set_bits(m, 2, 16, 0xffff, n); | ||
227 | } | ||
228 | |||
229 | static inline u32 msg_seqno(struct tipc_msg *m) | ||
230 | { | ||
231 | return msg_bits(m, 2, 0, 0xffff); | ||
232 | } | ||
233 | |||
234 | static inline void msg_set_seqno(struct tipc_msg *m, u32 n) | ||
235 | { | ||
236 | msg_set_bits(m, 2, 0, 0xffff, n); | ||
237 | } | ||
238 | |||
239 | |||
240 | /* | ||
241 | * Words 3-10 | ||
242 | */ | ||
243 | |||
244 | |||
245 | static inline void msg_set_prevnode(struct tipc_msg *m, u32 a) | ||
246 | { | ||
247 | msg_set_word(m, 3, a); | ||
248 | } | ||
249 | |||
250 | static inline void msg_set_origport(struct tipc_msg *m, u32 p) | ||
251 | { | ||
252 | msg_set_word(m, 4, p); | ||
253 | } | ||
254 | |||
255 | static inline void msg_set_destport(struct tipc_msg *m, u32 p) | ||
256 | { | ||
257 | msg_set_word(m, 5, p); | ||
258 | } | ||
259 | |||
260 | static inline void msg_set_mc_netid(struct tipc_msg *m, u32 p) | ||
261 | { | ||
262 | msg_set_word(m, 5, p); | ||
263 | } | ||
264 | |||
265 | static inline void msg_set_orignode(struct tipc_msg *m, u32 a) | ||
266 | { | ||
267 | msg_set_word(m, 6, a); | ||
268 | } | ||
269 | |||
270 | static inline void msg_set_destnode(struct tipc_msg *m, u32 a) | ||
271 | { | ||
272 | msg_set_word(m, 7, a); | ||
273 | } | ||
274 | |||
275 | static inline int msg_is_dest(struct tipc_msg *m, u32 d) | ||
276 | { | ||
277 | return(msg_short(m) || (msg_destnode(m) == d)); | ||
278 | } | ||
279 | |||
280 | static inline u32 msg_routed(struct tipc_msg *m) | ||
281 | { | ||
282 | if (likely(msg_short(m))) | ||
283 | return 0; | ||
284 | return(msg_destnode(m) ^ msg_orignode(m)) >> 11; | ||
285 | } | ||
286 | |||
287 | static inline void msg_set_nametype(struct tipc_msg *m, u32 n) | ||
288 | { | ||
289 | msg_set_word(m, 8, n); | ||
290 | } | ||
291 | |||
292 | static inline u32 msg_transp_seqno(struct tipc_msg *m) | ||
293 | { | ||
294 | return msg_word(m, 8); | ||
295 | } | ||
296 | |||
297 | static inline void msg_set_timestamp(struct tipc_msg *m, u32 n) | ||
298 | { | ||
299 | msg_set_word(m, 8, n); | ||
300 | } | ||
301 | |||
302 | static inline u32 msg_timestamp(struct tipc_msg *m) | ||
303 | { | ||
304 | return msg_word(m, 8); | ||
305 | } | ||
306 | |||
307 | static inline void msg_set_transp_seqno(struct tipc_msg *m, u32 n) | ||
308 | { | ||
309 | msg_set_word(m, 8, n); | ||
310 | } | ||
311 | |||
312 | static inline void msg_set_namelower(struct tipc_msg *m, u32 n) | ||
313 | { | ||
314 | msg_set_word(m, 9, n); | ||
315 | } | ||
316 | |||
317 | static inline void msg_set_nameinst(struct tipc_msg *m, u32 n) | ||
318 | { | ||
319 | msg_set_namelower(m, n); | ||
320 | } | ||
321 | |||
322 | static inline void msg_set_nameupper(struct tipc_msg *m, u32 n) | ||
323 | { | ||
324 | msg_set_word(m, 10, n); | ||
325 | } | ||
326 | |||
327 | static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) | ||
328 | { | ||
329 | return (struct tipc_msg *)msg_data(m); | ||
330 | } | ||
331 | |||
332 | static inline void msg_expand(struct tipc_msg *m, u32 destnode) | ||
333 | { | ||
334 | if (!msg_short(m)) | ||
335 | return; | ||
336 | msg_set_hdr_sz(m, LONG_H_SIZE); | ||
337 | msg_set_orignode(m, msg_prevnode(m)); | ||
338 | msg_set_destnode(m, destnode); | ||
339 | memset(&m->hdr[8], 0, 12); | ||
340 | } | ||
341 | |||
342 | |||
343 | |||
344 | /* | ||
345 | TIPC internal message header format, version 2 | ||
346 | |||
347 | 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0 | ||
348 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
349 | w0:|vers |msg usr|hdr sz |n|resrv| packet size | | ||
350 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
351 | w1:|m typ|rsv=0| sequence gap | broadcast ack no | | ||
352 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
353 | w2:| link level ack no/bc_gap_from | seq no / bcast_gap_to | | ||
354 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
355 | w3:| previous node | | ||
356 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
357 | w4:| next sent broadcast/fragm no | next sent pkt/ fragm msg no | | ||
358 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
359 | w5:| session no |rsv=0|r|berid|link prio|netpl|p| | ||
360 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
361 | w6:| originating node | | ||
362 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
363 | w7:| destination node | | ||
364 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
365 | w8:| transport sequence number | | ||
366 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
367 | w9:| msg count / bcast tag | link tolerance | | ||
368 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
369 | \ \ | ||
370 | / User Specific Data / | ||
371 | \ \ | ||
372 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
373 | |||
374 | NB: CONN_MANAGER use data message format. LINK_CONFIG has own format. | ||
375 | */ | ||
376 | |||
377 | /* | ||
378 | * Internal users | ||
379 | */ | ||
380 | |||
381 | #define BCAST_PROTOCOL 5 | ||
382 | #define MSG_BUNDLER 6 | ||
383 | #define LINK_PROTOCOL 7 | ||
384 | #define CONN_MANAGER 8 | ||
385 | #define ROUTE_DISTRIBUTOR 9 | ||
386 | #define CHANGEOVER_PROTOCOL 10 | ||
387 | #define NAME_DISTRIBUTOR 11 | ||
388 | #define MSG_FRAGMENTER 12 | ||
389 | #define LINK_CONFIG 13 | ||
390 | #define INT_H_SIZE 40 | ||
391 | #define DSC_H_SIZE 40 | ||
392 | |||
393 | /* | ||
394 | * Connection management protocol messages | ||
395 | */ | ||
396 | |||
397 | #define CONN_PROBE 0 | ||
398 | #define CONN_PROBE_REPLY 1 | ||
399 | #define CONN_ACK 2 | ||
400 | |||
401 | /* | ||
402 | * Name distributor messages | ||
403 | */ | ||
404 | |||
405 | #define PUBLICATION 0 | ||
406 | #define WITHDRAWAL 1 | ||
407 | |||
408 | |||
409 | /* | ||
410 | * Word 1 | ||
411 | */ | ||
412 | |||
413 | static inline u32 msg_seq_gap(struct tipc_msg *m) | ||
414 | { | ||
415 | return msg_bits(m, 1, 16, 0xff); | ||
416 | } | ||
417 | |||
418 | static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n) | ||
419 | { | ||
420 | msg_set_bits(m, 1, 16, 0xff, n); | ||
421 | } | ||
422 | |||
423 | static inline u32 msg_req_links(struct tipc_msg *m) | ||
424 | { | ||
425 | return msg_bits(m, 1, 16, 0xfff); | ||
426 | } | ||
427 | |||
428 | static inline void msg_set_req_links(struct tipc_msg *m, u32 n) | ||
429 | { | ||
430 | msg_set_bits(m, 1, 16, 0xfff, n); | ||
431 | } | ||
432 | |||
433 | |||
434 | /* | ||
435 | * Word 2 | ||
436 | */ | ||
437 | |||
438 | static inline u32 msg_dest_domain(struct tipc_msg *m) | ||
439 | { | ||
440 | return msg_word(m, 2); | ||
441 | } | ||
442 | |||
443 | static inline void msg_set_dest_domain(struct tipc_msg *m, u32 n) | ||
444 | { | ||
445 | msg_set_word(m, 2, n); | ||
446 | } | ||
447 | |||
448 | static inline u32 msg_bcgap_after(struct tipc_msg *m) | ||
449 | { | ||
450 | return msg_bits(m, 2, 16, 0xffff); | ||
451 | } | ||
452 | |||
453 | static inline void msg_set_bcgap_after(struct tipc_msg *m, u32 n) | ||
454 | { | ||
455 | msg_set_bits(m, 2, 16, 0xffff, n); | ||
456 | } | ||
457 | |||
458 | static inline u32 msg_bcgap_to(struct tipc_msg *m) | ||
459 | { | ||
460 | return msg_bits(m, 2, 0, 0xffff); | ||
461 | } | ||
462 | |||
463 | static inline void msg_set_bcgap_to(struct tipc_msg *m, u32 n) | ||
464 | { | ||
465 | msg_set_bits(m, 2, 0, 0xffff, n); | ||
466 | } | ||
467 | |||
468 | |||
469 | /* | ||
470 | * Word 4 | ||
471 | */ | ||
472 | |||
473 | static inline u32 msg_last_bcast(struct tipc_msg *m) | ||
474 | { | ||
475 | return msg_bits(m, 4, 16, 0xffff); | ||
476 | } | ||
477 | |||
478 | static inline void msg_set_last_bcast(struct tipc_msg *m, u32 n) | ||
479 | { | ||
480 | msg_set_bits(m, 4, 16, 0xffff, n); | ||
481 | } | ||
482 | |||
483 | |||
484 | static inline u32 msg_fragm_no(struct tipc_msg *m) | ||
485 | { | ||
486 | return msg_bits(m, 4, 16, 0xffff); | ||
487 | } | ||
488 | |||
489 | static inline void msg_set_fragm_no(struct tipc_msg *m, u32 n) | ||
490 | { | ||
491 | msg_set_bits(m, 4, 16, 0xffff, n); | ||
492 | } | ||
493 | |||
494 | |||
495 | static inline u32 msg_next_sent(struct tipc_msg *m) | ||
496 | { | ||
497 | return msg_bits(m, 4, 0, 0xffff); | ||
498 | } | ||
499 | |||
500 | static inline void msg_set_next_sent(struct tipc_msg *m, u32 n) | ||
501 | { | ||
502 | msg_set_bits(m, 4, 0, 0xffff, n); | ||
503 | } | ||
504 | |||
505 | |||
506 | static inline u32 msg_long_msgno(struct tipc_msg *m) | ||
507 | { | ||
508 | return msg_bits(m, 4, 0, 0xffff); | ||
509 | } | ||
510 | |||
511 | static inline void msg_set_long_msgno(struct tipc_msg *m, u32 n) | ||
512 | { | ||
513 | msg_set_bits(m, 4, 0, 0xffff, n); | ||
514 | } | ||
515 | |||
516 | static inline u32 msg_bc_netid(struct tipc_msg *m) | ||
517 | { | ||
518 | return msg_word(m, 4); | ||
519 | } | ||
520 | |||
521 | static inline void msg_set_bc_netid(struct tipc_msg *m, u32 id) | ||
522 | { | ||
523 | msg_set_word(m, 4, id); | ||
524 | } | ||
525 | |||
526 | static inline u32 msg_link_selector(struct tipc_msg *m) | ||
527 | { | ||
528 | return msg_bits(m, 4, 0, 1); | ||
529 | } | ||
530 | |||
531 | static inline void msg_set_link_selector(struct tipc_msg *m, u32 n) | ||
532 | { | ||
533 | msg_set_bits(m, 4, 0, 1, (n & 1)); | ||
534 | } | ||
535 | |||
536 | /* | ||
537 | * Word 5 | ||
538 | */ | ||
539 | |||
540 | static inline u32 msg_session(struct tipc_msg *m) | ||
541 | { | ||
542 | return msg_bits(m, 5, 16, 0xffff); | ||
543 | } | ||
544 | |||
545 | static inline void msg_set_session(struct tipc_msg *m, u32 n) | ||
546 | { | ||
547 | msg_set_bits(m, 5, 16, 0xffff, n); | ||
548 | } | ||
549 | |||
550 | static inline u32 msg_probe(struct tipc_msg *m) | ||
551 | { | ||
552 | return msg_bits(m, 5, 0, 1); | ||
553 | } | ||
554 | |||
555 | static inline void msg_set_probe(struct tipc_msg *m, u32 val) | ||
556 | { | ||
557 | msg_set_bits(m, 5, 0, 1, (val & 1)); | ||
558 | } | ||
559 | |||
560 | static inline char msg_net_plane(struct tipc_msg *m) | ||
561 | { | ||
562 | return msg_bits(m, 5, 1, 7) + 'A'; | ||
563 | } | ||
564 | |||
565 | static inline void msg_set_net_plane(struct tipc_msg *m, char n) | ||
566 | { | ||
567 | msg_set_bits(m, 5, 1, 7, (n - 'A')); | ||
568 | } | ||
569 | |||
570 | static inline u32 msg_linkprio(struct tipc_msg *m) | ||
571 | { | ||
572 | return msg_bits(m, 5, 4, 0x1f); | ||
573 | } | ||
574 | |||
575 | static inline void msg_set_linkprio(struct tipc_msg *m, u32 n) | ||
576 | { | ||
577 | msg_set_bits(m, 5, 4, 0x1f, n); | ||
578 | } | ||
579 | |||
580 | static inline u32 msg_bearer_id(struct tipc_msg *m) | ||
581 | { | ||
582 | return msg_bits(m, 5, 9, 0x7); | ||
583 | } | ||
584 | |||
585 | static inline void msg_set_bearer_id(struct tipc_msg *m, u32 n) | ||
586 | { | ||
587 | msg_set_bits(m, 5, 9, 0x7, n); | ||
588 | } | ||
589 | |||
590 | static inline u32 msg_redundant_link(struct tipc_msg *m) | ||
591 | { | ||
592 | return msg_bits(m, 5, 12, 0x1); | ||
593 | } | ||
594 | |||
595 | static inline void msg_set_redundant_link(struct tipc_msg *m) | ||
596 | { | ||
597 | msg_set_bits(m, 5, 12, 0x1, 1); | ||
598 | } | ||
599 | |||
600 | static inline void msg_clear_redundant_link(struct tipc_msg *m) | ||
601 | { | ||
602 | msg_set_bits(m, 5, 12, 0x1, 0); | ||
603 | } | ||
604 | |||
605 | |||
606 | /* | ||
607 | * Word 9 | ||
608 | */ | ||
609 | |||
610 | static inline u32 msg_msgcnt(struct tipc_msg *m) | ||
611 | { | ||
612 | return msg_bits(m, 9, 16, 0xffff); | ||
613 | } | ||
614 | |||
615 | static inline void msg_set_msgcnt(struct tipc_msg *m, u32 n) | ||
616 | { | ||
617 | msg_set_bits(m, 9, 16, 0xffff, n); | ||
618 | } | ||
619 | |||
620 | static inline u32 msg_bcast_tag(struct tipc_msg *m) | ||
621 | { | ||
622 | return msg_bits(m, 9, 16, 0xffff); | ||
623 | } | ||
624 | |||
625 | static inline void msg_set_bcast_tag(struct tipc_msg *m, u32 n) | ||
626 | { | ||
627 | msg_set_bits(m, 9, 16, 0xffff, n); | ||
628 | } | ||
629 | |||
630 | static inline u32 msg_max_pkt(struct tipc_msg *m) | ||
631 | { | ||
632 | return (msg_bits(m, 9, 16, 0xffff) * 4); | ||
633 | } | ||
634 | |||
635 | static inline void msg_set_max_pkt(struct tipc_msg *m, u32 n) | ||
636 | { | ||
637 | msg_set_bits(m, 9, 16, 0xffff, (n / 4)); | ||
638 | } | ||
639 | |||
640 | static inline u32 msg_link_tolerance(struct tipc_msg *m) | ||
641 | { | ||
642 | return msg_bits(m, 9, 0, 0xffff); | ||
643 | } | ||
644 | |||
645 | static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n) | ||
646 | { | ||
647 | msg_set_bits(m, 9, 0, 0xffff, n); | ||
648 | } | ||
649 | |||
650 | /* | ||
651 | * Routing table message data | ||
652 | */ | ||
653 | |||
654 | |||
655 | static inline u32 msg_remote_node(struct tipc_msg *m) | ||
656 | { | ||
657 | return msg_word(m, msg_hdr_sz(m)/4); | ||
658 | } | ||
659 | |||
660 | static inline void msg_set_remote_node(struct tipc_msg *m, u32 a) | ||
661 | { | ||
662 | msg_set_word(m, msg_hdr_sz(m)/4, a); | ||
663 | } | ||
664 | |||
665 | static inline int msg_dataoctet(struct tipc_msg *m, u32 pos) | ||
666 | { | ||
667 | return(msg_data(m)[pos + 4] != 0); | ||
668 | } | ||
669 | |||
670 | static inline void msg_set_dataoctet(struct tipc_msg *m, u32 pos) | ||
671 | { | ||
672 | msg_data(m)[pos + 4] = 1; | ||
673 | } | ||
674 | |||
675 | /* | ||
676 | * Segmentation message types | ||
677 | */ | ||
678 | |||
679 | #define FIRST_FRAGMENT 0 | ||
680 | #define FRAGMENT 1 | ||
681 | #define LAST_FRAGMENT 2 | ||
682 | |||
683 | /* | ||
684 | * Link management protocol message types | ||
685 | */ | ||
686 | |||
687 | #define STATE_MSG 0 | ||
688 | #define RESET_MSG 1 | ||
689 | #define ACTIVATE_MSG 2 | ||
690 | |||
691 | /* | ||
692 | * Changeover tunnel message types | ||
693 | */ | ||
694 | #define DUPLICATE_MSG 0 | ||
695 | #define ORIGINAL_MSG 1 | ||
696 | |||
697 | /* | ||
698 | * Routing table message types | ||
699 | */ | ||
700 | #define EXT_ROUTING_TABLE 0 | ||
701 | #define LOCAL_ROUTING_TABLE 1 | ||
702 | #define SLAVE_ROUTING_TABLE 2 | ||
703 | #define ROUTE_ADDITION 3 | ||
704 | #define ROUTE_REMOVAL 4 | ||
705 | |||
706 | /* | ||
707 | * Config protocol message types | ||
708 | */ | ||
709 | |||
710 | #define DSC_REQ_MSG 0 | ||
711 | #define DSC_RESP_MSG 1 | ||
712 | |||
713 | static inline u32 msg_tot_importance(struct tipc_msg *m) | ||
714 | { | ||
715 | if (likely(msg_isdata(m))) { | ||
716 | if (likely(msg_orignode(m) == tipc_own_addr)) | ||
717 | return msg_importance(m); | ||
718 | return msg_importance(m) + 4; | ||
719 | } | ||
720 | if ((msg_user(m) == MSG_FRAGMENTER) && | ||
721 | (msg_type(m) == FIRST_FRAGMENT)) | ||
722 | return msg_importance(msg_get_wrapped(m)); | ||
723 | return msg_importance(m); | ||
724 | } | ||
725 | |||
726 | |||
727 | static inline void msg_init(struct tipc_msg *m, u32 user, u32 type, | ||
728 | u32 err, u32 hsize, u32 destnode) | ||
729 | { | ||
730 | memset(m, 0, hsize); | ||
731 | msg_set_version(m); | ||
732 | msg_set_user(m, user); | ||
733 | msg_set_hdr_sz(m, hsize); | ||
734 | msg_set_size(m, hsize); | ||
735 | msg_set_prevnode(m, tipc_own_addr); | ||
736 | msg_set_type(m, type); | ||
737 | msg_set_errcode(m, err); | ||
738 | if (!msg_short(m)) { | ||
739 | msg_set_orignode(m, tipc_own_addr); | ||
740 | msg_set_destnode(m, destnode); | ||
741 | } | ||
742 | } | ||
743 | |||
744 | /** | ||
745 | * msg_calc_data_size - determine total data size for message | ||
746 | */ | ||
747 | |||
748 | static inline int msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) | ||
749 | { | ||
750 | int dsz = 0; | ||
751 | int i; | ||
752 | |||
753 | for (i = 0; i < num_sect; i++) | ||
754 | dsz += msg_sect[i].iov_len; | ||
755 | return dsz; | ||
756 | } | ||
757 | |||
758 | /** | ||
759 | * msg_build - create message using specified header and data | ||
760 | * | ||
761 | * Note: Caller must not hold any locks in case copy_from_user() is interrupted! | ||
762 | * | ||
763 | * Returns message data size or errno | ||
764 | */ | ||
765 | |||
766 | static inline int msg_build(struct tipc_msg *hdr, | ||
767 | struct iovec const *msg_sect, u32 num_sect, | ||
768 | int max_size, int usrmem, struct sk_buff** buf) | ||
769 | { | ||
770 | int dsz, sz, hsz, pos, res, cnt; | ||
771 | |||
772 | dsz = msg_calc_data_size(msg_sect, num_sect); | ||
773 | if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) { | ||
774 | *buf = NULL; | ||
775 | return -EINVAL; | ||
776 | } | ||
777 | |||
778 | pos = hsz = msg_hdr_sz(hdr); | ||
779 | sz = hsz + dsz; | ||
780 | msg_set_size(hdr, sz); | ||
781 | if (unlikely(sz > max_size)) { | ||
782 | *buf = NULL; | ||
783 | return dsz; | ||
784 | } | ||
785 | |||
786 | *buf = buf_acquire(sz); | ||
787 | if (!(*buf)) | ||
788 | return -ENOMEM; | ||
789 | memcpy((*buf)->data, (unchar *)hdr, hsz); | ||
790 | for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) { | ||
791 | if (likely(usrmem)) | ||
792 | res = !copy_from_user((*buf)->data + pos, | ||
793 | msg_sect[cnt].iov_base, | ||
794 | msg_sect[cnt].iov_len); | ||
795 | else | ||
796 | memcpy((*buf)->data + pos, msg_sect[cnt].iov_base, | ||
797 | msg_sect[cnt].iov_len); | ||
798 | pos += msg_sect[cnt].iov_len; | ||
799 | } | ||
800 | if (likely(res)) | ||
801 | return dsz; | ||
802 | |||
803 | buf_discard(*buf); | ||
804 | *buf = NULL; | ||
805 | return -EFAULT; | ||
806 | } | ||
807 | |||
808 | |||
809 | struct tipc_media_addr; | ||
810 | |||
811 | extern void msg_set_media_addr(struct tipc_msg *m, | ||
812 | struct tipc_media_addr *a); | ||
813 | |||
814 | extern void msg_get_media_addr(struct tipc_msg *m, | ||
815 | struct tipc_media_addr *a); | ||
816 | |||
817 | |||
818 | #endif | ||
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c new file mode 100644 index 000000000000..41cbaf1a4a73 --- /dev/null +++ b/net/tipc/name_distr.c | |||
@@ -0,0 +1,309 @@ | |||
1 | /* | ||
2 | * net/tipc/name_distr.c: TIPC name distribution code | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "cluster.h" | ||
39 | #include "dbg.h" | ||
40 | #include "link.h" | ||
41 | #include "msg.h" | ||
42 | #include "name_distr.h" | ||
43 | |||
44 | #undef DBG_OUTPUT | ||
45 | #define DBG_OUTPUT NULL | ||
46 | |||
47 | #define ITEM_SIZE sizeof(struct distr_item) | ||
48 | |||
49 | /** | ||
50 | * struct distr_item - publication info distributed to other nodes | ||
51 | * @type: name sequence type | ||
52 | * @lower: name sequence lower bound | ||
53 | * @upper: name sequence upper bound | ||
54 | * @ref: publishing port reference | ||
55 | * @key: publication key | ||
56 | * | ||
57 | * ===> All fields are stored in network byte order. <=== | ||
58 | * | ||
59 | * First 3 fields identify (name or) name sequence being published. | ||
60 | * Reference field uniquely identifies port that published name sequence. | ||
61 | * Key field uniquely identifies publication, in the event a port has | ||
62 | * multiple publications of the same name sequence. | ||
63 | * | ||
64 | * Note: There is no field that identifies the publishing node because it is | ||
65 | * the same for all items contained within a publication message. | ||
66 | */ | ||
67 | |||
68 | struct distr_item { | ||
69 | u32 type; | ||
70 | u32 lower; | ||
71 | u32 upper; | ||
72 | u32 ref; | ||
73 | u32 key; | ||
74 | }; | ||
75 | |||
76 | /** | ||
77 | * List of externally visible publications by this node -- | ||
78 | * that is, all publications having scope > TIPC_NODE_SCOPE. | ||
79 | */ | ||
80 | |||
81 | static LIST_HEAD(publ_root); | ||
82 | static u32 publ_cnt = 0; | ||
83 | |||
84 | /** | ||
85 | * publ_to_item - add publication info to a publication message | ||
86 | */ | ||
87 | |||
88 | static void publ_to_item(struct distr_item *i, struct publication *p) | ||
89 | { | ||
90 | i->type = htonl(p->type); | ||
91 | i->lower = htonl(p->lower); | ||
92 | i->upper = htonl(p->upper); | ||
93 | i->ref = htonl(p->ref); | ||
94 | i->key = htonl(p->key); | ||
95 | dbg("publ_to_item: %u, %u, %u\n", p->type, p->lower, p->upper); | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * named_prepare_buf - allocate & initialize a publication message | ||
100 | */ | ||
101 | |||
102 | static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest) | ||
103 | { | ||
104 | struct sk_buff *buf = buf_acquire(LONG_H_SIZE + size); | ||
105 | struct tipc_msg *msg; | ||
106 | |||
107 | if (buf != NULL) { | ||
108 | msg = buf_msg(buf); | ||
109 | msg_init(msg, NAME_DISTRIBUTOR, type, TIPC_OK, | ||
110 | LONG_H_SIZE, dest); | ||
111 | msg_set_size(msg, LONG_H_SIZE + size); | ||
112 | } | ||
113 | return buf; | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * named_publish - tell other nodes about a new publication by this node | ||
118 | */ | ||
119 | |||
120 | void named_publish(struct publication *publ) | ||
121 | { | ||
122 | struct sk_buff *buf; | ||
123 | struct distr_item *item; | ||
124 | |||
125 | list_add(&publ->local_list, &publ_root); | ||
126 | publ_cnt++; | ||
127 | |||
128 | buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0); | ||
129 | if (!buf) { | ||
130 | warn("Memory squeeze; failed to distribute publication\n"); | ||
131 | return; | ||
132 | } | ||
133 | |||
134 | item = (struct distr_item *)msg_data(buf_msg(buf)); | ||
135 | publ_to_item(item, publ); | ||
136 | dbg("named_withdraw: broadcasting publish msg\n"); | ||
137 | cluster_broadcast(buf); | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * named_withdraw - tell other nodes about a withdrawn publication by this node | ||
142 | */ | ||
143 | |||
144 | void named_withdraw(struct publication *publ) | ||
145 | { | ||
146 | struct sk_buff *buf; | ||
147 | struct distr_item *item; | ||
148 | |||
149 | list_del(&publ->local_list); | ||
150 | publ_cnt--; | ||
151 | |||
152 | buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0); | ||
153 | if (!buf) { | ||
154 | warn("Memory squeeze; failed to distribute withdrawal\n"); | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | item = (struct distr_item *)msg_data(buf_msg(buf)); | ||
159 | publ_to_item(item, publ); | ||
160 | dbg("named_withdraw: broadcasting withdraw msg\n"); | ||
161 | cluster_broadcast(buf); | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * named_node_up - tell specified node about all publications by this node | ||
166 | */ | ||
167 | |||
168 | void named_node_up(unsigned long node) | ||
169 | { | ||
170 | struct publication *publ; | ||
171 | struct distr_item *item = 0; | ||
172 | struct sk_buff *buf = 0; | ||
173 | u32 left = 0; | ||
174 | u32 rest; | ||
175 | u32 max_item_buf; | ||
176 | |||
177 | assert(in_own_cluster(node)); | ||
178 | read_lock_bh(&nametbl_lock); | ||
179 | max_item_buf = TIPC_MAX_USER_MSG_SIZE / ITEM_SIZE; | ||
180 | max_item_buf *= ITEM_SIZE; | ||
181 | rest = publ_cnt * ITEM_SIZE; | ||
182 | |||
183 | list_for_each_entry(publ, &publ_root, local_list) { | ||
184 | if (!buf) { | ||
185 | left = (rest <= max_item_buf) ? rest : max_item_buf; | ||
186 | rest -= left; | ||
187 | buf = named_prepare_buf(PUBLICATION, left, node); | ||
188 | if (buf == NULL) { | ||
189 | warn("Memory Squeeze; could not send publication\n"); | ||
190 | goto exit; | ||
191 | } | ||
192 | item = (struct distr_item *)msg_data(buf_msg(buf)); | ||
193 | } | ||
194 | publ_to_item(item, publ); | ||
195 | item++; | ||
196 | left -= ITEM_SIZE; | ||
197 | if (!left) { | ||
198 | msg_set_link_selector(buf_msg(buf), node); | ||
199 | dbg("named_node_up: sending publish msg to " | ||
200 | "<%u.%u.%u>\n", tipc_zone(node), | ||
201 | tipc_cluster(node), tipc_node(node)); | ||
202 | link_send(buf, node, node); | ||
203 | buf = 0; | ||
204 | } | ||
205 | } | ||
206 | exit: | ||
207 | read_unlock_bh(&nametbl_lock); | ||
208 | } | ||
209 | |||
210 | /** | ||
211 | * node_is_down - remove publication associated with a failed node | ||
212 | * | ||
213 | * Invoked for each publication issued by a newly failed node. | ||
214 | * Removes publication structure from name table & deletes it. | ||
215 | * In rare cases the link may have come back up again when this | ||
216 | * function is called, and we have two items representing the same | ||
217 | * publication. Nudge this item's key to distinguish it from the other. | ||
218 | * (Note: Publication's node subscription is already unsubscribed.) | ||
219 | */ | ||
220 | |||
221 | static void node_is_down(struct publication *publ) | ||
222 | { | ||
223 | struct publication *p; | ||
224 | write_lock_bh(&nametbl_lock); | ||
225 | dbg("node_is_down: withdrawing %u, %u, %u\n", | ||
226 | publ->type, publ->lower, publ->upper); | ||
227 | publ->key += 1222345; | ||
228 | p = nametbl_remove_publ(publ->type, publ->lower, | ||
229 | publ->node, publ->ref, publ->key); | ||
230 | assert(p == publ); | ||
231 | write_unlock_bh(&nametbl_lock); | ||
232 | if (publ) | ||
233 | kfree(publ); | ||
234 | } | ||
235 | |||
236 | /** | ||
237 | * named_recv - process name table update message sent by another node | ||
238 | */ | ||
239 | |||
240 | void named_recv(struct sk_buff *buf) | ||
241 | { | ||
242 | struct publication *publ; | ||
243 | struct tipc_msg *msg = buf_msg(buf); | ||
244 | struct distr_item *item = (struct distr_item *)msg_data(msg); | ||
245 | u32 count = msg_data_sz(msg) / ITEM_SIZE; | ||
246 | |||
247 | write_lock_bh(&nametbl_lock); | ||
248 | while (count--) { | ||
249 | if (msg_type(msg) == PUBLICATION) { | ||
250 | dbg("named_recv: got publication for %u, %u, %u\n", | ||
251 | ntohl(item->type), ntohl(item->lower), | ||
252 | ntohl(item->upper)); | ||
253 | publ = nametbl_insert_publ(ntohl(item->type), | ||
254 | ntohl(item->lower), | ||
255 | ntohl(item->upper), | ||
256 | TIPC_CLUSTER_SCOPE, | ||
257 | msg_orignode(msg), | ||
258 | ntohl(item->ref), | ||
259 | ntohl(item->key)); | ||
260 | if (publ) { | ||
261 | nodesub_subscribe(&publ->subscr, | ||
262 | msg_orignode(msg), | ||
263 | publ, | ||
264 | (net_ev_handler)node_is_down); | ||
265 | } | ||
266 | } else if (msg_type(msg) == WITHDRAWAL) { | ||
267 | dbg("named_recv: got withdrawl for %u, %u, %u\n", | ||
268 | ntohl(item->type), ntohl(item->lower), | ||
269 | ntohl(item->upper)); | ||
270 | publ = nametbl_remove_publ(ntohl(item->type), | ||
271 | ntohl(item->lower), | ||
272 | msg_orignode(msg), | ||
273 | ntohl(item->ref), | ||
274 | ntohl(item->key)); | ||
275 | |||
276 | if (publ) { | ||
277 | nodesub_unsubscribe(&publ->subscr); | ||
278 | kfree(publ); | ||
279 | } | ||
280 | } else { | ||
281 | warn("named_recv: unknown msg\n"); | ||
282 | } | ||
283 | item++; | ||
284 | } | ||
285 | write_unlock_bh(&nametbl_lock); | ||
286 | buf_discard(buf); | ||
287 | } | ||
288 | |||
289 | /** | ||
290 | * named_reinit - re-initialize local publication list | ||
291 | * | ||
292 | * This routine is called whenever TIPC networking is (re)enabled. | ||
293 | * All existing publications by this node that have "cluster" or "zone" scope | ||
294 | * are updated to reflect the node's current network address. | ||
295 | * (If the node's address is unchanged, the update loop terminates immediately.) | ||
296 | */ | ||
297 | |||
298 | void named_reinit(void) | ||
299 | { | ||
300 | struct publication *publ; | ||
301 | |||
302 | write_lock_bh(&nametbl_lock); | ||
303 | list_for_each_entry(publ, &publ_root, local_list) { | ||
304 | if (publ->node == tipc_own_addr) | ||
305 | break; | ||
306 | publ->node = tipc_own_addr; | ||
307 | } | ||
308 | write_unlock_bh(&nametbl_lock); | ||
309 | } | ||
diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h new file mode 100644 index 000000000000..a04bdeac84ea --- /dev/null +++ b/net/tipc/name_distr.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * net/tipc/name_distr.h: Include file for TIPC name distribution code | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_NAME_DISTR_H | ||
38 | #define _TIPC_NAME_DISTR_H | ||
39 | |||
40 | #include "name_table.h" | ||
41 | |||
42 | void named_publish(struct publication *publ); | ||
43 | void named_withdraw(struct publication *publ); | ||
44 | void named_node_up(unsigned long node); | ||
45 | void named_recv(struct sk_buff *buf); | ||
46 | void named_reinit(void); | ||
47 | |||
48 | #endif | ||
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c new file mode 100644 index 000000000000..972c83eb83b4 --- /dev/null +++ b/net/tipc/name_table.c | |||
@@ -0,0 +1,1079 @@ | |||
1 | /* | ||
2 | * net/tipc/name_table.c: TIPC name table code | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "config.h" | ||
39 | #include "dbg.h" | ||
40 | #include "name_table.h" | ||
41 | #include "name_distr.h" | ||
42 | #include "addr.h" | ||
43 | #include "node_subscr.h" | ||
44 | #include "subscr.h" | ||
45 | #include "port.h" | ||
46 | #include "cluster.h" | ||
47 | #include "bcast.h" | ||
48 | |||
49 | int tipc_nametbl_size = 1024; /* must be a power of 2 */ | ||
50 | |||
51 | /** | ||
52 | * struct sub_seq - container for all published instances of a name sequence | ||
53 | * @lower: name sequence lower bound | ||
54 | * @upper: name sequence upper bound | ||
55 | * @node_list: circular list of matching publications with >= node scope | ||
56 | * @cluster_list: circular list of matching publications with >= cluster scope | ||
57 | * @zone_list: circular list of matching publications with >= zone scope | ||
58 | */ | ||
59 | |||
60 | struct sub_seq { | ||
61 | u32 lower; | ||
62 | u32 upper; | ||
63 | struct publication *node_list; | ||
64 | struct publication *cluster_list; | ||
65 | struct publication *zone_list; | ||
66 | }; | ||
67 | |||
68 | /** | ||
69 | * struct name_seq - container for all published instances of a name type | ||
70 | * @type: 32 bit 'type' value for name sequence | ||
71 | * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type'; | ||
72 | * sub-sequences are sorted in ascending order | ||
73 | * @alloc: number of sub-sequences currently in array | ||
74 | * @first_free: upper bound of highest sub-sequence + 1 | ||
75 | * @ns_list: links to adjacent name sequences in hash chain | ||
76 | * @subscriptions: list of subscriptions for this 'type' | ||
77 | * @lock: spinlock controlling access to name sequence structure | ||
78 | */ | ||
79 | |||
80 | struct name_seq { | ||
81 | u32 type; | ||
82 | struct sub_seq *sseqs; | ||
83 | u32 alloc; | ||
84 | u32 first_free; | ||
85 | struct hlist_node ns_list; | ||
86 | struct list_head subscriptions; | ||
87 | spinlock_t lock; | ||
88 | }; | ||
89 | |||
90 | /** | ||
91 | * struct name_table - table containing all existing port name publications | ||
92 | * @types: pointer to fixed-sized array of name sequence lists, | ||
93 | * accessed via hashing on 'type'; name sequence lists are *not* sorted | ||
94 | * @local_publ_count: number of publications issued by this node | ||
95 | */ | ||
96 | |||
97 | struct name_table { | ||
98 | struct hlist_head *types; | ||
99 | u32 local_publ_count; | ||
100 | }; | ||
101 | |||
102 | struct name_table table = { NULL } ; | ||
103 | static atomic_t rsv_publ_ok = ATOMIC_INIT(0); | ||
104 | rwlock_t nametbl_lock = RW_LOCK_UNLOCKED; | ||
105 | |||
106 | |||
107 | static inline int hash(int x) | ||
108 | { | ||
109 | return(x & (tipc_nametbl_size - 1)); | ||
110 | } | ||
111 | |||
112 | /** | ||
113 | * publ_create - create a publication structure | ||
114 | */ | ||
115 | |||
116 | static struct publication *publ_create(u32 type, u32 lower, u32 upper, | ||
117 | u32 scope, u32 node, u32 port_ref, | ||
118 | u32 key) | ||
119 | { | ||
120 | struct publication *publ = | ||
121 | (struct publication *)kmalloc(sizeof(*publ), GFP_ATOMIC); | ||
122 | if (publ == NULL) { | ||
123 | warn("Memory squeeze; failed to create publication\n"); | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | memset(publ, 0, sizeof(*publ)); | ||
128 | publ->type = type; | ||
129 | publ->lower = lower; | ||
130 | publ->upper = upper; | ||
131 | publ->scope = scope; | ||
132 | publ->node = node; | ||
133 | publ->ref = port_ref; | ||
134 | publ->key = key; | ||
135 | INIT_LIST_HEAD(&publ->local_list); | ||
136 | INIT_LIST_HEAD(&publ->pport_list); | ||
137 | INIT_LIST_HEAD(&publ->subscr.nodesub_list); | ||
138 | return publ; | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * subseq_alloc - allocate a specified number of sub-sequence structures | ||
143 | */ | ||
144 | |||
145 | struct sub_seq *subseq_alloc(u32 cnt) | ||
146 | { | ||
147 | u32 sz = cnt * sizeof(struct sub_seq); | ||
148 | struct sub_seq *sseq = (struct sub_seq *)kmalloc(sz, GFP_ATOMIC); | ||
149 | |||
150 | if (sseq) | ||
151 | memset(sseq, 0, sz); | ||
152 | return sseq; | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * nameseq_create - create a name sequence structure for the specified 'type' | ||
157 | * | ||
158 | * Allocates a single sub-sequence structure and sets it to all 0's. | ||
159 | */ | ||
160 | |||
161 | struct name_seq *nameseq_create(u32 type, struct hlist_head *seq_head) | ||
162 | { | ||
163 | struct name_seq *nseq = | ||
164 | (struct name_seq *)kmalloc(sizeof(*nseq), GFP_ATOMIC); | ||
165 | struct sub_seq *sseq = subseq_alloc(1); | ||
166 | |||
167 | if (!nseq || !sseq) { | ||
168 | warn("Memory squeeze; failed to create name sequence\n"); | ||
169 | kfree(nseq); | ||
170 | kfree(sseq); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | memset(nseq, 0, sizeof(*nseq)); | ||
175 | nseq->lock = SPIN_LOCK_UNLOCKED; | ||
176 | nseq->type = type; | ||
177 | nseq->sseqs = sseq; | ||
178 | dbg("nameseq_create() nseq = %x type %u, ssseqs %x, ff: %u\n", | ||
179 | nseq, type, nseq->sseqs, nseq->first_free); | ||
180 | nseq->alloc = 1; | ||
181 | INIT_HLIST_NODE(&nseq->ns_list); | ||
182 | INIT_LIST_HEAD(&nseq->subscriptions); | ||
183 | hlist_add_head(&nseq->ns_list, seq_head); | ||
184 | return nseq; | ||
185 | } | ||
186 | |||
187 | /** | ||
188 | * nameseq_find_subseq - find sub-sequence (if any) matching a name instance | ||
189 | * | ||
190 | * Very time-critical, so binary searches through sub-sequence array. | ||
191 | */ | ||
192 | |||
193 | static inline struct sub_seq *nameseq_find_subseq(struct name_seq *nseq, | ||
194 | u32 instance) | ||
195 | { | ||
196 | struct sub_seq *sseqs = nseq->sseqs; | ||
197 | int low = 0; | ||
198 | int high = nseq->first_free - 1; | ||
199 | int mid; | ||
200 | |||
201 | while (low <= high) { | ||
202 | mid = (low + high) / 2; | ||
203 | if (instance < sseqs[mid].lower) | ||
204 | high = mid - 1; | ||
205 | else if (instance > sseqs[mid].upper) | ||
206 | low = mid + 1; | ||
207 | else | ||
208 | return &sseqs[mid]; | ||
209 | } | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | /** | ||
214 | * nameseq_locate_subseq - determine position of name instance in sub-sequence | ||
215 | * | ||
216 | * Returns index in sub-sequence array of the entry that contains the specified | ||
217 | * instance value; if no entry contains that value, returns the position | ||
218 | * where a new entry for it would be inserted in the array. | ||
219 | * | ||
220 | * Note: Similar to binary search code for locating a sub-sequence. | ||
221 | */ | ||
222 | |||
223 | static u32 nameseq_locate_subseq(struct name_seq *nseq, u32 instance) | ||
224 | { | ||
225 | struct sub_seq *sseqs = nseq->sseqs; | ||
226 | int low = 0; | ||
227 | int high = nseq->first_free - 1; | ||
228 | int mid; | ||
229 | |||
230 | while (low <= high) { | ||
231 | mid = (low + high) / 2; | ||
232 | if (instance < sseqs[mid].lower) | ||
233 | high = mid - 1; | ||
234 | else if (instance > sseqs[mid].upper) | ||
235 | low = mid + 1; | ||
236 | else | ||
237 | return mid; | ||
238 | } | ||
239 | return low; | ||
240 | } | ||
241 | |||
242 | /** | ||
243 | * nameseq_insert_publ - | ||
244 | */ | ||
245 | |||
246 | struct publication *nameseq_insert_publ(struct name_seq *nseq, | ||
247 | u32 type, u32 lower, u32 upper, | ||
248 | u32 scope, u32 node, u32 port, u32 key) | ||
249 | { | ||
250 | struct subscription *s; | ||
251 | struct subscription *st; | ||
252 | struct publication *publ; | ||
253 | struct sub_seq *sseq; | ||
254 | int created_subseq = 0; | ||
255 | |||
256 | assert(nseq->first_free <= nseq->alloc); | ||
257 | sseq = nameseq_find_subseq(nseq, lower); | ||
258 | dbg("nameseq_ins: for seq %x,<%u,%u>, found sseq %x\n", | ||
259 | nseq, type, lower, sseq); | ||
260 | if (sseq) { | ||
261 | |||
262 | /* Lower end overlaps existing entry => need an exact match */ | ||
263 | |||
264 | if ((sseq->lower != lower) || (sseq->upper != upper)) { | ||
265 | warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); | ||
266 | return 0; | ||
267 | } | ||
268 | } else { | ||
269 | u32 inspos; | ||
270 | struct sub_seq *freesseq; | ||
271 | |||
272 | /* Find where lower end should be inserted */ | ||
273 | |||
274 | inspos = nameseq_locate_subseq(nseq, lower); | ||
275 | |||
276 | /* Fail if upper end overlaps into an existing entry */ | ||
277 | |||
278 | if ((inspos < nseq->first_free) && | ||
279 | (upper >= nseq->sseqs[inspos].lower)) { | ||
280 | warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | /* Ensure there is space for new sub-sequence */ | ||
285 | |||
286 | if (nseq->first_free == nseq->alloc) { | ||
287 | struct sub_seq *sseqs = nseq->sseqs; | ||
288 | nseq->sseqs = subseq_alloc(nseq->alloc * 2); | ||
289 | if (nseq->sseqs != NULL) { | ||
290 | memcpy(nseq->sseqs, sseqs, | ||
291 | nseq->alloc * sizeof (struct sub_seq)); | ||
292 | kfree(sseqs); | ||
293 | dbg("Allocated %u sseqs\n", nseq->alloc); | ||
294 | nseq->alloc *= 2; | ||
295 | } else { | ||
296 | warn("Memory squeeze; failed to create sub-sequence\n"); | ||
297 | return 0; | ||
298 | } | ||
299 | } | ||
300 | dbg("Have %u sseqs for type %u\n", nseq->alloc, type); | ||
301 | |||
302 | /* Insert new sub-sequence */ | ||
303 | |||
304 | dbg("ins in pos %u, ff = %u\n", inspos, nseq->first_free); | ||
305 | sseq = &nseq->sseqs[inspos]; | ||
306 | freesseq = &nseq->sseqs[nseq->first_free]; | ||
307 | memmove(sseq + 1, sseq, (freesseq - sseq) * sizeof (*sseq)); | ||
308 | memset(sseq, 0, sizeof (*sseq)); | ||
309 | nseq->first_free++; | ||
310 | sseq->lower = lower; | ||
311 | sseq->upper = upper; | ||
312 | created_subseq = 1; | ||
313 | } | ||
314 | dbg("inserting (%u %u %u) from %x:%u into sseq %x(%u,%u) of seq %x\n", | ||
315 | type, lower, upper, node, port, sseq, | ||
316 | sseq->lower, sseq->upper, nseq); | ||
317 | |||
318 | /* Insert a publication: */ | ||
319 | |||
320 | publ = publ_create(type, lower, upper, scope, node, port, key); | ||
321 | if (!publ) | ||
322 | return 0; | ||
323 | dbg("inserting publ %x, node=%x publ->node=%x, subscr->node=%x\n", | ||
324 | publ, node, publ->node, publ->subscr.node); | ||
325 | |||
326 | if (!sseq->zone_list) | ||
327 | sseq->zone_list = publ->zone_list_next = publ; | ||
328 | else { | ||
329 | publ->zone_list_next = sseq->zone_list->zone_list_next; | ||
330 | sseq->zone_list->zone_list_next = publ; | ||
331 | } | ||
332 | |||
333 | if (in_own_cluster(node)) { | ||
334 | if (!sseq->cluster_list) | ||
335 | sseq->cluster_list = publ->cluster_list_next = publ; | ||
336 | else { | ||
337 | publ->cluster_list_next = | ||
338 | sseq->cluster_list->cluster_list_next; | ||
339 | sseq->cluster_list->cluster_list_next = publ; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | if (node == tipc_own_addr) { | ||
344 | if (!sseq->node_list) | ||
345 | sseq->node_list = publ->node_list_next = publ; | ||
346 | else { | ||
347 | publ->node_list_next = sseq->node_list->node_list_next; | ||
348 | sseq->node_list->node_list_next = publ; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | /* | ||
353 | * Any subscriptions waiting for notification? | ||
354 | */ | ||
355 | list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { | ||
356 | dbg("calling report_overlap()\n"); | ||
357 | subscr_report_overlap(s, | ||
358 | publ->lower, | ||
359 | publ->upper, | ||
360 | TIPC_PUBLISHED, | ||
361 | publ->ref, | ||
362 | publ->node, | ||
363 | created_subseq); | ||
364 | } | ||
365 | return publ; | ||
366 | } | ||
367 | |||
368 | /** | ||
369 | * nameseq_remove_publ - | ||
370 | */ | ||
371 | |||
372 | struct publication *nameseq_remove_publ(struct name_seq *nseq, u32 inst, | ||
373 | u32 node, u32 ref, u32 key) | ||
374 | { | ||
375 | struct publication *publ; | ||
376 | struct publication *prev; | ||
377 | struct sub_seq *sseq = nameseq_find_subseq(nseq, inst); | ||
378 | struct sub_seq *free; | ||
379 | struct subscription *s, *st; | ||
380 | int removed_subseq = 0; | ||
381 | |||
382 | assert(nseq); | ||
383 | |||
384 | if (!sseq) { | ||
385 | int i; | ||
386 | |||
387 | warn("Withdraw unknown <%u,%u>?\n", nseq->type, inst); | ||
388 | assert(nseq->sseqs); | ||
389 | dbg("Dumping subseqs %x for %x, alloc = %u,ff=%u\n", | ||
390 | nseq->sseqs, nseq, nseq->alloc, | ||
391 | nseq->first_free); | ||
392 | for (i = 0; i < nseq->first_free; i++) { | ||
393 | dbg("Subseq %u(%x): lower = %u,upper = %u\n", | ||
394 | i, &nseq->sseqs[i], nseq->sseqs[i].lower, | ||
395 | nseq->sseqs[i].upper); | ||
396 | } | ||
397 | return 0; | ||
398 | } | ||
399 | dbg("nameseq_remove: seq: %x, sseq %x, <%u,%u> key %u\n", | ||
400 | nseq, sseq, nseq->type, inst, key); | ||
401 | |||
402 | prev = sseq->zone_list; | ||
403 | publ = sseq->zone_list->zone_list_next; | ||
404 | while ((publ->key != key) || (publ->ref != ref) || | ||
405 | (publ->node && (publ->node != node))) { | ||
406 | prev = publ; | ||
407 | publ = publ->zone_list_next; | ||
408 | assert(prev != sseq->zone_list); | ||
409 | } | ||
410 | if (publ != sseq->zone_list) | ||
411 | prev->zone_list_next = publ->zone_list_next; | ||
412 | else if (publ->zone_list_next != publ) { | ||
413 | prev->zone_list_next = publ->zone_list_next; | ||
414 | sseq->zone_list = publ->zone_list_next; | ||
415 | } else { | ||
416 | sseq->zone_list = 0; | ||
417 | } | ||
418 | |||
419 | if (in_own_cluster(node)) { | ||
420 | prev = sseq->cluster_list; | ||
421 | publ = sseq->cluster_list->cluster_list_next; | ||
422 | while ((publ->key != key) || (publ->ref != ref) || | ||
423 | (publ->node && (publ->node != node))) { | ||
424 | prev = publ; | ||
425 | publ = publ->cluster_list_next; | ||
426 | assert(prev != sseq->cluster_list); | ||
427 | } | ||
428 | if (publ != sseq->cluster_list) | ||
429 | prev->cluster_list_next = publ->cluster_list_next; | ||
430 | else if (publ->cluster_list_next != publ) { | ||
431 | prev->cluster_list_next = publ->cluster_list_next; | ||
432 | sseq->cluster_list = publ->cluster_list_next; | ||
433 | } else { | ||
434 | sseq->cluster_list = 0; | ||
435 | } | ||
436 | } | ||
437 | |||
438 | if (node == tipc_own_addr) { | ||
439 | prev = sseq->node_list; | ||
440 | publ = sseq->node_list->node_list_next; | ||
441 | while ((publ->key != key) || (publ->ref != ref) || | ||
442 | (publ->node && (publ->node != node))) { | ||
443 | prev = publ; | ||
444 | publ = publ->node_list_next; | ||
445 | assert(prev != sseq->node_list); | ||
446 | } | ||
447 | if (publ != sseq->node_list) | ||
448 | prev->node_list_next = publ->node_list_next; | ||
449 | else if (publ->node_list_next != publ) { | ||
450 | prev->node_list_next = publ->node_list_next; | ||
451 | sseq->node_list = publ->node_list_next; | ||
452 | } else { | ||
453 | sseq->node_list = 0; | ||
454 | } | ||
455 | } | ||
456 | assert(!publ->node || (publ->node == node)); | ||
457 | assert(publ->ref == ref); | ||
458 | assert(publ->key == key); | ||
459 | |||
460 | /* | ||
461 | * Contract subseq list if no more publications: | ||
462 | */ | ||
463 | if (!sseq->node_list && !sseq->cluster_list && !sseq->zone_list) { | ||
464 | free = &nseq->sseqs[nseq->first_free--]; | ||
465 | memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof (*sseq)); | ||
466 | removed_subseq = 1; | ||
467 | } | ||
468 | |||
469 | /* | ||
470 | * Any subscriptions waiting ? | ||
471 | */ | ||
472 | list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { | ||
473 | subscr_report_overlap(s, | ||
474 | publ->lower, | ||
475 | publ->upper, | ||
476 | TIPC_WITHDRAWN, | ||
477 | publ->ref, | ||
478 | publ->node, | ||
479 | removed_subseq); | ||
480 | } | ||
481 | return publ; | ||
482 | } | ||
483 | |||
484 | /** | ||
485 | * nameseq_subscribe: attach a subscription, and issue | ||
486 | * the prescribed number of events if there is any sub- | ||
487 | * sequence overlapping with the requested sequence | ||
488 | */ | ||
489 | |||
490 | void nameseq_subscribe(struct name_seq *nseq, struct subscription *s) | ||
491 | { | ||
492 | struct sub_seq *sseq = nseq->sseqs; | ||
493 | |||
494 | list_add(&s->nameseq_list, &nseq->subscriptions); | ||
495 | |||
496 | if (!sseq) | ||
497 | return; | ||
498 | |||
499 | while (sseq != &nseq->sseqs[nseq->first_free]) { | ||
500 | struct publication *zl = sseq->zone_list; | ||
501 | if (zl && subscr_overlap(s,sseq->lower,sseq->upper)) { | ||
502 | struct publication *crs = zl; | ||
503 | int must_report = 1; | ||
504 | |||
505 | do { | ||
506 | subscr_report_overlap(s, | ||
507 | sseq->lower, | ||
508 | sseq->upper, | ||
509 | TIPC_PUBLISHED, | ||
510 | crs->ref, | ||
511 | crs->node, | ||
512 | must_report); | ||
513 | must_report = 0; | ||
514 | crs = crs->zone_list_next; | ||
515 | } while (crs != zl); | ||
516 | } | ||
517 | sseq++; | ||
518 | } | ||
519 | } | ||
520 | |||
521 | static struct name_seq *nametbl_find_seq(u32 type) | ||
522 | { | ||
523 | struct hlist_head *seq_head; | ||
524 | struct hlist_node *seq_node; | ||
525 | struct name_seq *ns; | ||
526 | |||
527 | dbg("find_seq %u,(%u,0x%x) table = %p, hash[type] = %u\n", | ||
528 | type, ntohl(type), type, table.types, hash(type)); | ||
529 | |||
530 | seq_head = &table.types[hash(type)]; | ||
531 | hlist_for_each_entry(ns, seq_node, seq_head, ns_list) { | ||
532 | if (ns->type == type) { | ||
533 | dbg("found %x\n", ns); | ||
534 | return ns; | ||
535 | } | ||
536 | } | ||
537 | |||
538 | return 0; | ||
539 | }; | ||
540 | |||
541 | struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper, | ||
542 | u32 scope, u32 node, u32 port, u32 key) | ||
543 | { | ||
544 | struct name_seq *seq = nametbl_find_seq(type); | ||
545 | |||
546 | dbg("ins_publ: <%u,%x,%x> found %x\n", type, lower, upper, seq); | ||
547 | if (lower > upper) { | ||
548 | warn("Failed to publish illegal <%u,%u,%u>\n", | ||
549 | type, lower, upper); | ||
550 | return 0; | ||
551 | } | ||
552 | |||
553 | dbg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node); | ||
554 | if (!seq) { | ||
555 | seq = nameseq_create(type, &table.types[hash(type)]); | ||
556 | dbg("nametbl_insert_publ: created %x\n", seq); | ||
557 | } | ||
558 | if (!seq) | ||
559 | return 0; | ||
560 | |||
561 | assert(seq->type == type); | ||
562 | return nameseq_insert_publ(seq, type, lower, upper, | ||
563 | scope, node, port, key); | ||
564 | } | ||
565 | |||
566 | struct publication *nametbl_remove_publ(u32 type, u32 lower, | ||
567 | u32 node, u32 ref, u32 key) | ||
568 | { | ||
569 | struct publication *publ; | ||
570 | struct name_seq *seq = nametbl_find_seq(type); | ||
571 | |||
572 | if (!seq) | ||
573 | return 0; | ||
574 | |||
575 | dbg("Withdrawing <%u,%u> from %x\n", type, lower, node); | ||
576 | publ = nameseq_remove_publ(seq, lower, node, ref, key); | ||
577 | |||
578 | if (!seq->first_free && list_empty(&seq->subscriptions)) { | ||
579 | hlist_del_init(&seq->ns_list); | ||
580 | kfree(seq->sseqs); | ||
581 | kfree(seq); | ||
582 | } | ||
583 | return publ; | ||
584 | } | ||
585 | |||
586 | /* | ||
587 | * nametbl_translate(): Translate tipc_name -> tipc_portid. | ||
588 | * Very time-critical. | ||
589 | * | ||
590 | * Note: on entry 'destnode' is the search domain used during translation; | ||
591 | * on exit it passes back the node address of the matching port (if any) | ||
592 | */ | ||
593 | |||
594 | u32 nametbl_translate(u32 type, u32 instance, u32 *destnode) | ||
595 | { | ||
596 | struct sub_seq *sseq; | ||
597 | struct publication *publ = 0; | ||
598 | struct name_seq *seq; | ||
599 | u32 ref; | ||
600 | |||
601 | if (!in_scope(*destnode, tipc_own_addr)) | ||
602 | return 0; | ||
603 | |||
604 | read_lock_bh(&nametbl_lock); | ||
605 | seq = nametbl_find_seq(type); | ||
606 | if (unlikely(!seq)) | ||
607 | goto not_found; | ||
608 | sseq = nameseq_find_subseq(seq, instance); | ||
609 | if (unlikely(!sseq)) | ||
610 | goto not_found; | ||
611 | spin_lock_bh(&seq->lock); | ||
612 | |||
613 | /* Closest-First Algorithm: */ | ||
614 | if (likely(!*destnode)) { | ||
615 | publ = sseq->node_list; | ||
616 | if (publ) { | ||
617 | sseq->node_list = publ->node_list_next; | ||
618 | found: | ||
619 | ref = publ->ref; | ||
620 | *destnode = publ->node; | ||
621 | spin_unlock_bh(&seq->lock); | ||
622 | read_unlock_bh(&nametbl_lock); | ||
623 | return ref; | ||
624 | } | ||
625 | publ = sseq->cluster_list; | ||
626 | if (publ) { | ||
627 | sseq->cluster_list = publ->cluster_list_next; | ||
628 | goto found; | ||
629 | } | ||
630 | publ = sseq->zone_list; | ||
631 | if (publ) { | ||
632 | sseq->zone_list = publ->zone_list_next; | ||
633 | goto found; | ||
634 | } | ||
635 | } | ||
636 | |||
637 | /* Round-Robin Algorithm: */ | ||
638 | else if (*destnode == tipc_own_addr) { | ||
639 | publ = sseq->node_list; | ||
640 | if (publ) { | ||
641 | sseq->node_list = publ->node_list_next; | ||
642 | goto found; | ||
643 | } | ||
644 | } else if (in_own_cluster(*destnode)) { | ||
645 | publ = sseq->cluster_list; | ||
646 | if (publ) { | ||
647 | sseq->cluster_list = publ->cluster_list_next; | ||
648 | goto found; | ||
649 | } | ||
650 | } else { | ||
651 | publ = sseq->zone_list; | ||
652 | if (publ) { | ||
653 | sseq->zone_list = publ->zone_list_next; | ||
654 | goto found; | ||
655 | } | ||
656 | } | ||
657 | spin_unlock_bh(&seq->lock); | ||
658 | not_found: | ||
659 | *destnode = 0; | ||
660 | read_unlock_bh(&nametbl_lock); | ||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | /** | ||
665 | * nametbl_mc_translate - find multicast destinations | ||
666 | * | ||
667 | * Creates list of all local ports that overlap the given multicast address; | ||
668 | * also determines if any off-node ports overlap. | ||
669 | * | ||
670 | * Note: Publications with a scope narrower than 'limit' are ignored. | ||
671 | * (i.e. local node-scope publications mustn't receive messages arriving | ||
672 | * from another node, even if the multcast link brought it here) | ||
673 | * | ||
674 | * Returns non-zero if any off-node ports overlap | ||
675 | */ | ||
676 | |||
677 | int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, | ||
678 | struct port_list *dports) | ||
679 | { | ||
680 | struct name_seq *seq; | ||
681 | struct sub_seq *sseq; | ||
682 | struct sub_seq *sseq_stop; | ||
683 | int res = 0; | ||
684 | |||
685 | read_lock_bh(&nametbl_lock); | ||
686 | seq = nametbl_find_seq(type); | ||
687 | if (!seq) | ||
688 | goto exit; | ||
689 | |||
690 | spin_lock_bh(&seq->lock); | ||
691 | |||
692 | sseq = seq->sseqs + nameseq_locate_subseq(seq, lower); | ||
693 | sseq_stop = seq->sseqs + seq->first_free; | ||
694 | for (; sseq != sseq_stop; sseq++) { | ||
695 | struct publication *publ; | ||
696 | |||
697 | if (sseq->lower > upper) | ||
698 | break; | ||
699 | publ = sseq->cluster_list; | ||
700 | if (publ && (publ->scope <= limit)) | ||
701 | do { | ||
702 | if (publ->node == tipc_own_addr) | ||
703 | port_list_add(dports, publ->ref); | ||
704 | else | ||
705 | res = 1; | ||
706 | publ = publ->cluster_list_next; | ||
707 | } while (publ != sseq->cluster_list); | ||
708 | } | ||
709 | |||
710 | spin_unlock_bh(&seq->lock); | ||
711 | exit: | ||
712 | read_unlock_bh(&nametbl_lock); | ||
713 | return res; | ||
714 | } | ||
715 | |||
716 | /** | ||
717 | * nametbl_publish_rsv - publish port name using a reserved name type | ||
718 | */ | ||
719 | |||
720 | int nametbl_publish_rsv(u32 ref, unsigned int scope, | ||
721 | struct tipc_name_seq const *seq) | ||
722 | { | ||
723 | int res; | ||
724 | |||
725 | atomic_inc(&rsv_publ_ok); | ||
726 | res = tipc_publish(ref, scope, seq); | ||
727 | atomic_dec(&rsv_publ_ok); | ||
728 | return res; | ||
729 | } | ||
730 | |||
731 | /** | ||
732 | * nametbl_publish - add name publication to network name tables | ||
733 | */ | ||
734 | |||
735 | struct publication *nametbl_publish(u32 type, u32 lower, u32 upper, | ||
736 | u32 scope, u32 port_ref, u32 key) | ||
737 | { | ||
738 | struct publication *publ; | ||
739 | |||
740 | if (table.local_publ_count >= tipc_max_publications) { | ||
741 | warn("Failed publish: max %u local publication\n", | ||
742 | tipc_max_publications); | ||
743 | return 0; | ||
744 | } | ||
745 | if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) { | ||
746 | warn("Failed to publish reserved name <%u,%u,%u>\n", | ||
747 | type, lower, upper); | ||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | write_lock_bh(&nametbl_lock); | ||
752 | table.local_publ_count++; | ||
753 | publ = nametbl_insert_publ(type, lower, upper, scope, | ||
754 | tipc_own_addr, port_ref, key); | ||
755 | if (publ && (scope != TIPC_NODE_SCOPE)) { | ||
756 | named_publish(publ); | ||
757 | } | ||
758 | write_unlock_bh(&nametbl_lock); | ||
759 | return publ; | ||
760 | } | ||
761 | |||
762 | /** | ||
763 | * nametbl_withdraw - withdraw name publication from network name tables | ||
764 | */ | ||
765 | |||
766 | int nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) | ||
767 | { | ||
768 | struct publication *publ; | ||
769 | |||
770 | dbg("nametbl_withdraw:<%d,%d,%d>\n", type, lower, key); | ||
771 | write_lock_bh(&nametbl_lock); | ||
772 | publ = nametbl_remove_publ(type, lower, tipc_own_addr, ref, key); | ||
773 | if (publ) { | ||
774 | table.local_publ_count--; | ||
775 | if (publ->scope != TIPC_NODE_SCOPE) | ||
776 | named_withdraw(publ); | ||
777 | write_unlock_bh(&nametbl_lock); | ||
778 | list_del_init(&publ->pport_list); | ||
779 | kfree(publ); | ||
780 | return 1; | ||
781 | } | ||
782 | write_unlock_bh(&nametbl_lock); | ||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | /** | ||
787 | * nametbl_subscribe - add a subscription object to the name table | ||
788 | */ | ||
789 | |||
790 | void | ||
791 | nametbl_subscribe(struct subscription *s) | ||
792 | { | ||
793 | u32 type = s->seq.type; | ||
794 | struct name_seq *seq; | ||
795 | |||
796 | write_lock_bh(&nametbl_lock); | ||
797 | seq = nametbl_find_seq(type); | ||
798 | if (!seq) { | ||
799 | seq = nameseq_create(type, &table.types[hash(type)]); | ||
800 | } | ||
801 | if (seq){ | ||
802 | spin_lock_bh(&seq->lock); | ||
803 | dbg("nametbl_subscribe:found %x for <%u,%u,%u>\n", | ||
804 | seq, type, s->seq.lower, s->seq.upper); | ||
805 | assert(seq->type == type); | ||
806 | nameseq_subscribe(seq, s); | ||
807 | spin_unlock_bh(&seq->lock); | ||
808 | } | ||
809 | write_unlock_bh(&nametbl_lock); | ||
810 | } | ||
811 | |||
812 | /** | ||
813 | * nametbl_unsubscribe - remove a subscription object from name table | ||
814 | */ | ||
815 | |||
816 | void | ||
817 | nametbl_unsubscribe(struct subscription *s) | ||
818 | { | ||
819 | struct name_seq *seq; | ||
820 | |||
821 | write_lock_bh(&nametbl_lock); | ||
822 | seq = nametbl_find_seq(s->seq.type); | ||
823 | if (seq != NULL){ | ||
824 | spin_lock_bh(&seq->lock); | ||
825 | list_del_init(&s->nameseq_list); | ||
826 | spin_unlock_bh(&seq->lock); | ||
827 | if ((seq->first_free == 0) && list_empty(&seq->subscriptions)) { | ||
828 | hlist_del_init(&seq->ns_list); | ||
829 | kfree(seq->sseqs); | ||
830 | kfree(seq); | ||
831 | } | ||
832 | } | ||
833 | write_unlock_bh(&nametbl_lock); | ||
834 | } | ||
835 | |||
836 | |||
837 | /** | ||
838 | * subseq_list: print specified sub-sequence contents into the given buffer | ||
839 | */ | ||
840 | |||
841 | static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth, | ||
842 | u32 index) | ||
843 | { | ||
844 | char portIdStr[27]; | ||
845 | char *scopeStr; | ||
846 | struct publication *publ = sseq->zone_list; | ||
847 | |||
848 | tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper); | ||
849 | |||
850 | if (depth == 2 || !publ) { | ||
851 | tipc_printf(buf, "\n"); | ||
852 | return; | ||
853 | } | ||
854 | |||
855 | do { | ||
856 | sprintf (portIdStr, "<%u.%u.%u:%u>", | ||
857 | tipc_zone(publ->node), tipc_cluster(publ->node), | ||
858 | tipc_node(publ->node), publ->ref); | ||
859 | tipc_printf(buf, "%-26s ", portIdStr); | ||
860 | if (depth > 3) { | ||
861 | if (publ->node != tipc_own_addr) | ||
862 | scopeStr = ""; | ||
863 | else if (publ->scope == TIPC_NODE_SCOPE) | ||
864 | scopeStr = "node"; | ||
865 | else if (publ->scope == TIPC_CLUSTER_SCOPE) | ||
866 | scopeStr = "cluster"; | ||
867 | else | ||
868 | scopeStr = "zone"; | ||
869 | tipc_printf(buf, "%-10u %s", publ->key, scopeStr); | ||
870 | } | ||
871 | |||
872 | publ = publ->zone_list_next; | ||
873 | if (publ == sseq->zone_list) | ||
874 | break; | ||
875 | |||
876 | tipc_printf(buf, "\n%33s", " "); | ||
877 | } while (1); | ||
878 | |||
879 | tipc_printf(buf, "\n"); | ||
880 | } | ||
881 | |||
882 | /** | ||
883 | * nameseq_list: print specified name sequence contents into the given buffer | ||
884 | */ | ||
885 | |||
886 | static void nameseq_list(struct name_seq *seq, struct print_buf *buf, u32 depth, | ||
887 | u32 type, u32 lowbound, u32 upbound, u32 index) | ||
888 | { | ||
889 | struct sub_seq *sseq; | ||
890 | char typearea[11]; | ||
891 | |||
892 | sprintf(typearea, "%-10u", seq->type); | ||
893 | |||
894 | if (depth == 1) { | ||
895 | tipc_printf(buf, "%s\n", typearea); | ||
896 | return; | ||
897 | } | ||
898 | |||
899 | for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) { | ||
900 | if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) { | ||
901 | tipc_printf(buf, "%s ", typearea); | ||
902 | subseq_list(sseq, buf, depth, index); | ||
903 | sprintf(typearea, "%10s", " "); | ||
904 | } | ||
905 | } | ||
906 | } | ||
907 | |||
908 | /** | ||
909 | * nametbl_header - print name table header into the given buffer | ||
910 | */ | ||
911 | |||
912 | static void nametbl_header(struct print_buf *buf, u32 depth) | ||
913 | { | ||
914 | tipc_printf(buf, "Type "); | ||
915 | |||
916 | if (depth > 1) | ||
917 | tipc_printf(buf, "Lower Upper "); | ||
918 | if (depth > 2) | ||
919 | tipc_printf(buf, "Port Identity "); | ||
920 | if (depth > 3) | ||
921 | tipc_printf(buf, "Publication"); | ||
922 | |||
923 | tipc_printf(buf, "\n-----------"); | ||
924 | |||
925 | if (depth > 1) | ||
926 | tipc_printf(buf, "--------------------- "); | ||
927 | if (depth > 2) | ||
928 | tipc_printf(buf, "-------------------------- "); | ||
929 | if (depth > 3) | ||
930 | tipc_printf(buf, "------------------"); | ||
931 | |||
932 | tipc_printf(buf, "\n"); | ||
933 | } | ||
934 | |||
935 | /** | ||
936 | * nametbl_list - print specified name table contents into the given buffer | ||
937 | */ | ||
938 | |||
939 | static void nametbl_list(struct print_buf *buf, u32 depth_info, | ||
940 | u32 type, u32 lowbound, u32 upbound) | ||
941 | { | ||
942 | struct hlist_head *seq_head; | ||
943 | struct hlist_node *seq_node; | ||
944 | struct name_seq *seq; | ||
945 | int all_types; | ||
946 | u32 depth; | ||
947 | u32 i; | ||
948 | |||
949 | all_types = (depth_info & TIPC_NTQ_ALLTYPES); | ||
950 | depth = (depth_info & ~TIPC_NTQ_ALLTYPES); | ||
951 | |||
952 | if (depth == 0) | ||
953 | return; | ||
954 | |||
955 | if (all_types) { | ||
956 | /* display all entries in name table to specified depth */ | ||
957 | nametbl_header(buf, depth); | ||
958 | lowbound = 0; | ||
959 | upbound = ~0; | ||
960 | for (i = 0; i < tipc_nametbl_size; i++) { | ||
961 | seq_head = &table.types[i]; | ||
962 | hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { | ||
963 | nameseq_list(seq, buf, depth, seq->type, | ||
964 | lowbound, upbound, i); | ||
965 | } | ||
966 | } | ||
967 | } else { | ||
968 | /* display only the sequence that matches the specified type */ | ||
969 | if (upbound < lowbound) { | ||
970 | tipc_printf(buf, "invalid name sequence specified\n"); | ||
971 | return; | ||
972 | } | ||
973 | nametbl_header(buf, depth); | ||
974 | i = hash(type); | ||
975 | seq_head = &table.types[i]; | ||
976 | hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { | ||
977 | if (seq->type == type) { | ||
978 | nameseq_list(seq, buf, depth, type, | ||
979 | lowbound, upbound, i); | ||
980 | break; | ||
981 | } | ||
982 | } | ||
983 | } | ||
984 | } | ||
985 | |||
986 | void nametbl_print(struct print_buf *buf, const char *str) | ||
987 | { | ||
988 | tipc_printf(buf, str); | ||
989 | read_lock_bh(&nametbl_lock); | ||
990 | nametbl_list(buf, 0, 0, 0, 0); | ||
991 | read_unlock_bh(&nametbl_lock); | ||
992 | } | ||
993 | |||
994 | #define MAX_NAME_TBL_QUERY 32768 | ||
995 | |||
996 | struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space) | ||
997 | { | ||
998 | struct sk_buff *buf; | ||
999 | struct tipc_name_table_query *argv; | ||
1000 | struct tlv_desc *rep_tlv; | ||
1001 | struct print_buf b; | ||
1002 | int str_len; | ||
1003 | |||
1004 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY)) | ||
1005 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
1006 | |||
1007 | buf = cfg_reply_alloc(TLV_SPACE(MAX_NAME_TBL_QUERY)); | ||
1008 | if (!buf) | ||
1009 | return NULL; | ||
1010 | |||
1011 | rep_tlv = (struct tlv_desc *)buf->data; | ||
1012 | printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY); | ||
1013 | argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area); | ||
1014 | read_lock_bh(&nametbl_lock); | ||
1015 | nametbl_list(&b, ntohl(argv->depth), ntohl(argv->type), | ||
1016 | ntohl(argv->lowbound), ntohl(argv->upbound)); | ||
1017 | read_unlock_bh(&nametbl_lock); | ||
1018 | str_len = printbuf_validate(&b); | ||
1019 | |||
1020 | skb_put(buf, TLV_SPACE(str_len)); | ||
1021 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | ||
1022 | |||
1023 | return buf; | ||
1024 | } | ||
1025 | |||
1026 | void nametbl_dump(void) | ||
1027 | { | ||
1028 | nametbl_list(CONS, 0, 0, 0, 0); | ||
1029 | } | ||
1030 | |||
1031 | int nametbl_init(void) | ||
1032 | { | ||
1033 | int array_size = sizeof(struct hlist_head) * tipc_nametbl_size; | ||
1034 | |||
1035 | table.types = (struct hlist_head *)kmalloc(array_size, GFP_ATOMIC); | ||
1036 | if (!table.types) | ||
1037 | return -ENOMEM; | ||
1038 | |||
1039 | write_lock_bh(&nametbl_lock); | ||
1040 | memset(table.types, 0, array_size); | ||
1041 | table.local_publ_count = 0; | ||
1042 | write_unlock_bh(&nametbl_lock); | ||
1043 | return 0; | ||
1044 | } | ||
1045 | |||
1046 | void nametbl_stop(void) | ||
1047 | { | ||
1048 | struct hlist_head *seq_head; | ||
1049 | struct hlist_node *seq_node; | ||
1050 | struct hlist_node *tmp; | ||
1051 | struct name_seq *seq; | ||
1052 | u32 i; | ||
1053 | |||
1054 | if (!table.types) | ||
1055 | return; | ||
1056 | |||
1057 | write_lock_bh(&nametbl_lock); | ||
1058 | for (i = 0; i < tipc_nametbl_size; i++) { | ||
1059 | seq_head = &table.types[i]; | ||
1060 | hlist_for_each_entry_safe(seq, seq_node, tmp, seq_head, ns_list) { | ||
1061 | struct sub_seq *sseq = seq->sseqs; | ||
1062 | |||
1063 | for (; sseq != &seq->sseqs[seq->first_free]; sseq++) { | ||
1064 | struct publication *publ = sseq->zone_list; | ||
1065 | assert(publ); | ||
1066 | do { | ||
1067 | struct publication *next = | ||
1068 | publ->zone_list_next; | ||
1069 | kfree(publ); | ||
1070 | publ = next; | ||
1071 | } | ||
1072 | while (publ != sseq->zone_list); | ||
1073 | } | ||
1074 | } | ||
1075 | } | ||
1076 | kfree(table.types); | ||
1077 | table.types = NULL; | ||
1078 | write_unlock_bh(&nametbl_lock); | ||
1079 | } | ||
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h new file mode 100644 index 000000000000..f82693384f60 --- /dev/null +++ b/net/tipc/name_table.h | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * net/tipc/name_table.h: Include file for TIPC name table code | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_NAME_TABLE_H | ||
38 | #define _TIPC_NAME_TABLE_H | ||
39 | |||
40 | #include "node_subscr.h" | ||
41 | |||
42 | struct subscription; | ||
43 | struct port_list; | ||
44 | |||
45 | /* | ||
46 | * TIPC name types reserved for internal TIPC use (both current and planned) | ||
47 | */ | ||
48 | |||
49 | #define TIPC_ZM_SRV 3 /* zone master service name type */ | ||
50 | |||
51 | |||
52 | /** | ||
53 | * struct publication - info about a published (name or) name sequence | ||
54 | * @type: name sequence type | ||
55 | * @lower: name sequence lower bound | ||
56 | * @upper: name sequence upper bound | ||
57 | * @scope: scope of publication | ||
58 | * @node: network address of publishing port's node | ||
59 | * @ref: publishing port | ||
60 | * @key: publication key | ||
61 | * @subscr: subscription to "node down" event (for off-node publications only) | ||
62 | * @local_list: adjacent entries in list of publications made by this node | ||
63 | * @pport_list: adjacent entries in list of publications made by this port | ||
64 | * @node_list: next matching name seq publication with >= node scope | ||
65 | * @cluster_list: next matching name seq publication with >= cluster scope | ||
66 | * @zone_list: next matching name seq publication with >= zone scope | ||
67 | * | ||
68 | * Note that the node list, cluster list, and zone list are circular lists. | ||
69 | */ | ||
70 | |||
71 | struct publication { | ||
72 | u32 type; | ||
73 | u32 lower; | ||
74 | u32 upper; | ||
75 | u32 scope; | ||
76 | u32 node; | ||
77 | u32 ref; | ||
78 | u32 key; | ||
79 | struct node_subscr subscr; | ||
80 | struct list_head local_list; | ||
81 | struct list_head pport_list; | ||
82 | struct publication *node_list_next; | ||
83 | struct publication *cluster_list_next; | ||
84 | struct publication *zone_list_next; | ||
85 | }; | ||
86 | |||
87 | |||
88 | extern rwlock_t nametbl_lock; | ||
89 | |||
90 | struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space); | ||
91 | u32 nametbl_translate(u32 type, u32 instance, u32 *node); | ||
92 | int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, | ||
93 | struct port_list *dports); | ||
94 | int nametbl_publish_rsv(u32 ref, unsigned int scope, | ||
95 | struct tipc_name_seq const *seq); | ||
96 | struct publication *nametbl_publish(u32 type, u32 lower, u32 upper, | ||
97 | u32 scope, u32 port_ref, u32 key); | ||
98 | int nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key); | ||
99 | struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper, | ||
100 | u32 scope, u32 node, u32 ref, u32 key); | ||
101 | struct publication *nametbl_remove_publ(u32 type, u32 lower, | ||
102 | u32 node, u32 ref, u32 key); | ||
103 | void nametbl_subscribe(struct subscription *s); | ||
104 | void nametbl_unsubscribe(struct subscription *s); | ||
105 | int nametbl_init(void); | ||
106 | void nametbl_stop(void); | ||
107 | |||
108 | #endif | ||
diff --git a/net/tipc/net.c b/net/tipc/net.c new file mode 100644 index 000000000000..6826b493c1d6 --- /dev/null +++ b/net/tipc/net.c | |||
@@ -0,0 +1,311 @@ | |||
1 | /* | ||
2 | * net/tipc/net.c: TIPC network routing code | ||
3 | * | ||
4 | * Copyright (c) 1995-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "bearer.h" | ||
39 | #include "net.h" | ||
40 | #include "zone.h" | ||
41 | #include "addr.h" | ||
42 | #include "name_table.h" | ||
43 | #include "name_distr.h" | ||
44 | #include "subscr.h" | ||
45 | #include "link.h" | ||
46 | #include "msg.h" | ||
47 | #include "port.h" | ||
48 | #include "bcast.h" | ||
49 | #include "discover.h" | ||
50 | #include "config.h" | ||
51 | |||
52 | /* | ||
53 | * The TIPC locking policy is designed to ensure a very fine locking | ||
54 | * granularity, permitting complete parallel access to individual | ||
55 | * port and node/link instances. The code consists of three major | ||
56 | * locking domains, each protected with their own disjunct set of locks. | ||
57 | * | ||
58 | * 1: The routing hierarchy. | ||
59 | * Comprises the structures 'zone', 'cluster', 'node', 'link' | ||
60 | * and 'bearer'. The whole hierarchy is protected by a big | ||
61 | * read/write lock, net_lock, to enssure that nothing is added | ||
62 | * or removed while code is accessing any of these structures. | ||
63 | * This layer must not be called from the two others while they | ||
64 | * hold any of their own locks. | ||
65 | * Neither must it itself do any upcalls to the other two before | ||
66 | * it has released net_lock and other protective locks. | ||
67 | * | ||
68 | * Within the net_lock domain there are two sub-domains;'node' and | ||
69 | * 'bearer', where local write operations are permitted, | ||
70 | * provided that those are protected by individual spin_locks | ||
71 | * per instance. Code holding net_lock(read) and a node spin_lock | ||
72 | * is permitted to poke around in both the node itself and its | ||
73 | * subordinate links. I.e, it can update link counters and queues, | ||
74 | * change link state, send protocol messages, and alter the | ||
75 | * "active_links" array in the node; but it can _not_ remove a link | ||
76 | * or a node from the overall structure. | ||
77 | * Correspondingly, individual bearers may change status within a | ||
78 | * net_lock(read), protected by an individual spin_lock ber bearer | ||
79 | * instance, but it needs net_lock(write) to remove/add any bearers. | ||
80 | * | ||
81 | * | ||
82 | * 2: The transport level of the protocol. | ||
83 | * This consists of the structures port, (and its user level | ||
84 | * representations, such as user_port and tipc_sock), reference and | ||
85 | * tipc_user (port.c, reg.c, socket.c). | ||
86 | * | ||
87 | * This layer has four different locks: | ||
88 | * - The tipc_port spin_lock. This is protecting each port instance | ||
89 | * from parallel data access and removal. Since we can not place | ||
90 | * this lock in the port itself, it has been placed in the | ||
91 | * corresponding reference table entry, which has the same life | ||
92 | * cycle as the module. This entry is difficult to access from | ||
93 | * outside the TIPC core, however, so a pointer to the lock has | ||
94 | * been added in the port instance, -to be used for unlocking | ||
95 | * only. | ||
96 | * - A read/write lock to protect the reference table itself (teg.c). | ||
97 | * (Nobody is using read-only access to this, so it can just as | ||
98 | * well be changed to a spin_lock) | ||
99 | * - A spin lock to protect the registry of kernel/driver users (reg.c) | ||
100 | * - A global spin_lock (port_lock), which only task is to ensure | ||
101 | * consistency where more than one port is involved in an operation, | ||
102 | * i.e., whe a port is part of a linked list of ports. | ||
103 | * There are two such lists; 'port_list', which is used for management, | ||
104 | * and 'wait_list', which is used to queue ports during congestion. | ||
105 | * | ||
106 | * 3: The name table (name_table.c, name_distr.c, subscription.c) | ||
107 | * - There is one big read/write-lock (nametbl_lock) protecting the | ||
108 | * overall name table structure. Nothing must be added/removed to | ||
109 | * this structure without holding write access to it. | ||
110 | * - There is one local spin_lock per sub_sequence, which can be seen | ||
111 | * as a sub-domain to the nametbl_lock domain. It is used only | ||
112 | * for translation operations, and is needed because a translation | ||
113 | * steps the root of the 'publication' linked list between each lookup. | ||
114 | * This is always used within the scope of a nametbl_lock(read). | ||
115 | * - A local spin_lock protecting the queue of subscriber events. | ||
116 | */ | ||
117 | |||
118 | rwlock_t net_lock = RW_LOCK_UNLOCKED; | ||
119 | struct network net = { 0 }; | ||
120 | |||
121 | struct node *net_select_remote_node(u32 addr, u32 ref) | ||
122 | { | ||
123 | return zone_select_remote_node(net.zones[tipc_zone(addr)], addr, ref); | ||
124 | } | ||
125 | |||
126 | u32 net_select_router(u32 addr, u32 ref) | ||
127 | { | ||
128 | return zone_select_router(net.zones[tipc_zone(addr)], addr, ref); | ||
129 | } | ||
130 | |||
131 | |||
132 | u32 net_next_node(u32 a) | ||
133 | { | ||
134 | if (net.zones[tipc_zone(a)]) | ||
135 | return zone_next_node(a); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | void net_remove_as_router(u32 router) | ||
140 | { | ||
141 | u32 z_num; | ||
142 | |||
143 | for (z_num = 1; z_num <= tipc_max_zones; z_num++) { | ||
144 | if (!net.zones[z_num]) | ||
145 | continue; | ||
146 | zone_remove_as_router(net.zones[z_num], router); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | void net_send_external_routes(u32 dest) | ||
151 | { | ||
152 | u32 z_num; | ||
153 | |||
154 | for (z_num = 1; z_num <= tipc_max_zones; z_num++) { | ||
155 | if (net.zones[z_num]) | ||
156 | zone_send_external_routes(net.zones[z_num], dest); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | int net_init(void) | ||
161 | { | ||
162 | u32 sz = sizeof(struct _zone *) * (tipc_max_zones + 1); | ||
163 | |||
164 | memset(&net, 0, sizeof(net)); | ||
165 | net.zones = (struct _zone **)kmalloc(sz, GFP_ATOMIC); | ||
166 | if (!net.zones) { | ||
167 | return -ENOMEM; | ||
168 | } | ||
169 | memset(net.zones, 0, sz); | ||
170 | return TIPC_OK; | ||
171 | } | ||
172 | |||
173 | void net_stop(void) | ||
174 | { | ||
175 | u32 z_num; | ||
176 | |||
177 | if (!net.zones) | ||
178 | return; | ||
179 | |||
180 | for (z_num = 1; z_num <= tipc_max_zones; z_num++) { | ||
181 | zone_delete(net.zones[z_num]); | ||
182 | } | ||
183 | kfree(net.zones); | ||
184 | net.zones = 0; | ||
185 | } | ||
186 | |||
187 | static void net_route_named_msg(struct sk_buff *buf) | ||
188 | { | ||
189 | struct tipc_msg *msg = buf_msg(buf); | ||
190 | u32 dnode; | ||
191 | u32 dport; | ||
192 | |||
193 | if (!msg_named(msg)) { | ||
194 | msg_dbg(msg, "net->drop_nam:"); | ||
195 | buf_discard(buf); | ||
196 | return; | ||
197 | } | ||
198 | |||
199 | dnode = addr_domain(msg_lookup_scope(msg)); | ||
200 | dport = nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode); | ||
201 | dbg("net->lookup<%u,%u>-><%u,%x>\n", | ||
202 | msg_nametype(msg), msg_nameinst(msg), dport, dnode); | ||
203 | if (dport) { | ||
204 | msg_set_destnode(msg, dnode); | ||
205 | msg_set_destport(msg, dport); | ||
206 | net_route_msg(buf); | ||
207 | return; | ||
208 | } | ||
209 | msg_dbg(msg, "net->rej:NO NAME: "); | ||
210 | tipc_reject_msg(buf, TIPC_ERR_NO_NAME); | ||
211 | } | ||
212 | |||
213 | void net_route_msg(struct sk_buff *buf) | ||
214 | { | ||
215 | struct tipc_msg *msg; | ||
216 | u32 dnode; | ||
217 | |||
218 | if (!buf) | ||
219 | return; | ||
220 | msg = buf_msg(buf); | ||
221 | |||
222 | msg_incr_reroute_cnt(msg); | ||
223 | if (msg_reroute_cnt(msg) > 6) { | ||
224 | if (msg_errcode(msg)) { | ||
225 | msg_dbg(msg, "NET>DISC>:"); | ||
226 | buf_discard(buf); | ||
227 | } else { | ||
228 | msg_dbg(msg, "NET>REJ>:"); | ||
229 | tipc_reject_msg(buf, msg_destport(msg) ? | ||
230 | TIPC_ERR_NO_PORT : TIPC_ERR_NO_NAME); | ||
231 | } | ||
232 | return; | ||
233 | } | ||
234 | |||
235 | msg_dbg(msg, "net->rout: "); | ||
236 | |||
237 | /* Handle message for this node */ | ||
238 | dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg); | ||
239 | if (in_scope(dnode, tipc_own_addr)) { | ||
240 | if (msg_isdata(msg)) { | ||
241 | if (msg_mcast(msg)) | ||
242 | port_recv_mcast(buf, NULL); | ||
243 | else if (msg_destport(msg)) | ||
244 | port_recv_msg(buf); | ||
245 | else | ||
246 | net_route_named_msg(buf); | ||
247 | return; | ||
248 | } | ||
249 | switch (msg_user(msg)) { | ||
250 | case ROUTE_DISTRIBUTOR: | ||
251 | cluster_recv_routing_table(buf); | ||
252 | break; | ||
253 | case NAME_DISTRIBUTOR: | ||
254 | named_recv(buf); | ||
255 | break; | ||
256 | case CONN_MANAGER: | ||
257 | port_recv_proto_msg(buf); | ||
258 | break; | ||
259 | default: | ||
260 | msg_dbg(msg,"DROP/NET/<REC<"); | ||
261 | buf_discard(buf); | ||
262 | } | ||
263 | return; | ||
264 | } | ||
265 | |||
266 | /* Handle message for another node */ | ||
267 | msg_dbg(msg, "NET>SEND>: "); | ||
268 | link_send(buf, dnode, msg_link_selector(msg)); | ||
269 | } | ||
270 | |||
271 | int tipc_start_net(void) | ||
272 | { | ||
273 | char addr_string[16]; | ||
274 | int res; | ||
275 | |||
276 | if (tipc_mode != TIPC_NODE_MODE) | ||
277 | return -ENOPROTOOPT; | ||
278 | |||
279 | tipc_mode = TIPC_NET_MODE; | ||
280 | named_reinit(); | ||
281 | port_reinit(); | ||
282 | |||
283 | if ((res = bearer_init()) || | ||
284 | (res = net_init()) || | ||
285 | (res = cluster_init()) || | ||
286 | (res = bclink_init())) { | ||
287 | return res; | ||
288 | } | ||
289 | subscr_stop(); | ||
290 | cfg_stop(); | ||
291 | k_signal((Handler)subscr_start, 0); | ||
292 | k_signal((Handler)cfg_init, 0); | ||
293 | info("Started in network mode\n"); | ||
294 | info("Own node address %s, network identity %u\n", | ||
295 | addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); | ||
296 | return TIPC_OK; | ||
297 | } | ||
298 | |||
299 | void tipc_stop_net(void) | ||
300 | { | ||
301 | if (tipc_mode != TIPC_NET_MODE) | ||
302 | return; | ||
303 | write_lock_bh(&net_lock); | ||
304 | bearer_stop(); | ||
305 | tipc_mode = TIPC_NODE_MODE; | ||
306 | bclink_stop(); | ||
307 | net_stop(); | ||
308 | write_unlock_bh(&net_lock); | ||
309 | info("Left network mode \n"); | ||
310 | } | ||
311 | |||
diff --git a/net/tipc/net.h b/net/tipc/net.h new file mode 100644 index 000000000000..948c6d42102c --- /dev/null +++ b/net/tipc/net.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * net/tipc/net.h: Include file for TIPC network routing code | ||
3 | * | ||
4 | * Copyright (c) 1995-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_NET_H | ||
38 | #define _TIPC_NET_H | ||
39 | |||
40 | struct _zone; | ||
41 | |||
42 | /** | ||
43 | * struct network - TIPC network structure | ||
44 | * @zones: array of pointers to all zones within network | ||
45 | */ | ||
46 | |||
47 | struct network { | ||
48 | struct _zone **zones; | ||
49 | }; | ||
50 | |||
51 | |||
52 | extern struct network net; | ||
53 | extern rwlock_t net_lock; | ||
54 | |||
55 | int net_init(void); | ||
56 | void net_stop(void); | ||
57 | void net_remove_as_router(u32 router); | ||
58 | void net_send_external_routes(u32 dest); | ||
59 | void net_route_msg(struct sk_buff *buf); | ||
60 | struct node *net_select_remote_node(u32 addr, u32 ref); | ||
61 | u32 net_select_router(u32 addr, u32 ref); | ||
62 | |||
63 | int tipc_start_net(void); | ||
64 | void tipc_stop_net(void); | ||
65 | |||
66 | #endif | ||
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c new file mode 100644 index 000000000000..19b3f4022532 --- /dev/null +++ b/net/tipc/netlink.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * net/tipc/netlink.c: TIPC configuration handling | ||
3 | * | ||
4 | * Copyright (c) 2005-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "config.h" | ||
39 | #include <net/genetlink.h> | ||
40 | |||
41 | static int handle_cmd(struct sk_buff *skb, struct genl_info *info) | ||
42 | { | ||
43 | struct sk_buff *rep_buf; | ||
44 | struct nlmsghdr *rep_nlh; | ||
45 | struct nlmsghdr *req_nlh = info->nlhdr; | ||
46 | struct tipc_genlmsghdr *req_userhdr = info->userhdr; | ||
47 | int hdr_space = NLMSG_SPACE(GENL_HDRLEN + TIPC_GENL_HDRLEN); | ||
48 | |||
49 | if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN))) | ||
50 | rep_buf = cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN); | ||
51 | else | ||
52 | rep_buf = cfg_do_cmd(req_userhdr->dest, | ||
53 | req_userhdr->cmd, | ||
54 | NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN, | ||
55 | NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN), | ||
56 | hdr_space); | ||
57 | |||
58 | if (rep_buf) { | ||
59 | skb_push(rep_buf, hdr_space); | ||
60 | rep_nlh = (struct nlmsghdr *)rep_buf->data; | ||
61 | memcpy(rep_nlh, req_nlh, hdr_space); | ||
62 | rep_nlh->nlmsg_len = rep_buf->len; | ||
63 | genlmsg_unicast(rep_buf, req_nlh->nlmsg_pid); | ||
64 | } | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static struct genl_family family = { | ||
70 | .id = GENL_ID_GENERATE, | ||
71 | .name = TIPC_GENL_NAME, | ||
72 | .version = TIPC_GENL_VERSION, | ||
73 | .hdrsize = TIPC_GENL_HDRLEN, | ||
74 | .maxattr = 0, | ||
75 | }; | ||
76 | |||
77 | static struct genl_ops ops = { | ||
78 | .cmd = TIPC_GENL_CMD, | ||
79 | .doit = handle_cmd, | ||
80 | }; | ||
81 | |||
82 | static int family_registered = 0; | ||
83 | |||
84 | int netlink_start(void) | ||
85 | { | ||
86 | |||
87 | |||
88 | if (genl_register_family(&family)) | ||
89 | goto err; | ||
90 | |||
91 | family_registered = 1; | ||
92 | |||
93 | if (genl_register_ops(&family, &ops)) | ||
94 | goto err_unregister; | ||
95 | |||
96 | return 0; | ||
97 | |||
98 | err_unregister: | ||
99 | genl_unregister_family(&family); | ||
100 | family_registered = 0; | ||
101 | err: | ||
102 | err("Failed to register netlink interface\n"); | ||
103 | return -EFAULT; | ||
104 | } | ||
105 | |||
106 | void netlink_stop(void) | ||
107 | { | ||
108 | if (family_registered) { | ||
109 | genl_unregister_family(&family); | ||
110 | family_registered = 0; | ||
111 | } | ||
112 | } | ||
diff --git a/net/tipc/node.c b/net/tipc/node.c new file mode 100644 index 000000000000..05688d01138b --- /dev/null +++ b/net/tipc/node.c | |||
@@ -0,0 +1,679 @@ | |||
1 | /* | ||
2 | * net/tipc/node.c: TIPC node management routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "config.h" | ||
39 | #include "node.h" | ||
40 | #include "cluster.h" | ||
41 | #include "net.h" | ||
42 | #include "addr.h" | ||
43 | #include "node_subscr.h" | ||
44 | #include "link.h" | ||
45 | #include "port.h" | ||
46 | #include "bearer.h" | ||
47 | #include "name_distr.h" | ||
48 | #include "net.h" | ||
49 | |||
50 | void node_print(struct print_buf *buf, struct node *n_ptr, char *str); | ||
51 | static void node_lost_contact(struct node *n_ptr); | ||
52 | static void node_established_contact(struct node *n_ptr); | ||
53 | |||
54 | struct node *nodes = NULL; /* sorted list of nodes within cluster */ | ||
55 | |||
56 | u32 tipc_own_tag = 0; | ||
57 | |||
58 | struct node *node_create(u32 addr) | ||
59 | { | ||
60 | struct cluster *c_ptr; | ||
61 | struct node *n_ptr; | ||
62 | struct node **curr_node; | ||
63 | |||
64 | n_ptr = kmalloc(sizeof(*n_ptr),GFP_ATOMIC); | ||
65 | if (n_ptr != NULL) { | ||
66 | memset(n_ptr, 0, sizeof(*n_ptr)); | ||
67 | n_ptr->addr = addr; | ||
68 | n_ptr->lock = SPIN_LOCK_UNLOCKED; | ||
69 | INIT_LIST_HEAD(&n_ptr->nsub); | ||
70 | |||
71 | c_ptr = cluster_find(addr); | ||
72 | if (c_ptr == NULL) | ||
73 | c_ptr = cluster_create(addr); | ||
74 | if (c_ptr != NULL) { | ||
75 | n_ptr->owner = c_ptr; | ||
76 | cluster_attach_node(c_ptr, n_ptr); | ||
77 | n_ptr->last_router = -1; | ||
78 | |||
79 | /* Insert node into ordered list */ | ||
80 | for (curr_node = &nodes; *curr_node; | ||
81 | curr_node = &(*curr_node)->next) { | ||
82 | if (addr < (*curr_node)->addr) { | ||
83 | n_ptr->next = *curr_node; | ||
84 | break; | ||
85 | } | ||
86 | } | ||
87 | (*curr_node) = n_ptr; | ||
88 | } else { | ||
89 | kfree(n_ptr); | ||
90 | n_ptr = NULL; | ||
91 | } | ||
92 | } | ||
93 | return n_ptr; | ||
94 | } | ||
95 | |||
96 | void node_delete(struct node *n_ptr) | ||
97 | { | ||
98 | if (!n_ptr) | ||
99 | return; | ||
100 | |||
101 | #if 0 | ||
102 | /* Not needed because links are already deleted via bearer_stop() */ | ||
103 | |||
104 | u32 l_num; | ||
105 | |||
106 | for (l_num = 0; l_num < MAX_BEARERS; l_num++) { | ||
107 | link_delete(n_ptr->links[l_num]); | ||
108 | } | ||
109 | #endif | ||
110 | |||
111 | dbg("node %x deleted\n", n_ptr->addr); | ||
112 | kfree(n_ptr); | ||
113 | } | ||
114 | |||
115 | |||
116 | /** | ||
117 | * node_link_up - handle addition of link | ||
118 | * | ||
119 | * Link becomes active (alone or shared) or standby, depending on its priority. | ||
120 | */ | ||
121 | |||
122 | void node_link_up(struct node *n_ptr, struct link *l_ptr) | ||
123 | { | ||
124 | struct link **active = &n_ptr->active_links[0]; | ||
125 | |||
126 | info("Established link <%s> on network plane %c\n", | ||
127 | l_ptr->name, l_ptr->b_ptr->net_plane); | ||
128 | |||
129 | if (!active[0]) { | ||
130 | dbg(" link %x into %x/%x\n", l_ptr, &active[0], &active[1]); | ||
131 | active[0] = active[1] = l_ptr; | ||
132 | node_established_contact(n_ptr); | ||
133 | return; | ||
134 | } | ||
135 | if (l_ptr->priority < active[0]->priority) { | ||
136 | info("Link is standby\n"); | ||
137 | return; | ||
138 | } | ||
139 | link_send_duplicate(active[0], l_ptr); | ||
140 | if (l_ptr->priority == active[0]->priority) { | ||
141 | active[0] = l_ptr; | ||
142 | return; | ||
143 | } | ||
144 | info("Link <%s> on network plane %c becomes standby\n", | ||
145 | active[0]->name, active[0]->b_ptr->net_plane); | ||
146 | active[0] = active[1] = l_ptr; | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * node_select_active_links - select active link | ||
151 | */ | ||
152 | |||
153 | static void node_select_active_links(struct node *n_ptr) | ||
154 | { | ||
155 | struct link **active = &n_ptr->active_links[0]; | ||
156 | u32 i; | ||
157 | u32 highest_prio = 0; | ||
158 | |||
159 | active[0] = active[1] = 0; | ||
160 | |||
161 | for (i = 0; i < MAX_BEARERS; i++) { | ||
162 | struct link *l_ptr = n_ptr->links[i]; | ||
163 | |||
164 | if (!l_ptr || !link_is_up(l_ptr) || | ||
165 | (l_ptr->priority < highest_prio)) | ||
166 | continue; | ||
167 | |||
168 | if (l_ptr->priority > highest_prio) { | ||
169 | highest_prio = l_ptr->priority; | ||
170 | active[0] = active[1] = l_ptr; | ||
171 | } else { | ||
172 | active[1] = l_ptr; | ||
173 | } | ||
174 | } | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * node_link_down - handle loss of link | ||
179 | */ | ||
180 | |||
181 | void node_link_down(struct node *n_ptr, struct link *l_ptr) | ||
182 | { | ||
183 | struct link **active; | ||
184 | |||
185 | if (!link_is_active(l_ptr)) { | ||
186 | info("Lost standby link <%s> on network plane %c\n", | ||
187 | l_ptr->name, l_ptr->b_ptr->net_plane); | ||
188 | return; | ||
189 | } | ||
190 | info("Lost link <%s> on network plane %c\n", | ||
191 | l_ptr->name, l_ptr->b_ptr->net_plane); | ||
192 | |||
193 | active = &n_ptr->active_links[0]; | ||
194 | if (active[0] == l_ptr) | ||
195 | active[0] = active[1]; | ||
196 | if (active[1] == l_ptr) | ||
197 | active[1] = active[0]; | ||
198 | if (active[0] == l_ptr) | ||
199 | node_select_active_links(n_ptr); | ||
200 | if (node_is_up(n_ptr)) | ||
201 | link_changeover(l_ptr); | ||
202 | else | ||
203 | node_lost_contact(n_ptr); | ||
204 | } | ||
205 | |||
206 | int node_has_active_links(struct node *n_ptr) | ||
207 | { | ||
208 | return (n_ptr && | ||
209 | ((n_ptr->active_links[0]) || (n_ptr->active_links[1]))); | ||
210 | } | ||
211 | |||
212 | int node_has_redundant_links(struct node *n_ptr) | ||
213 | { | ||
214 | return (node_has_active_links(n_ptr) && | ||
215 | (n_ptr->active_links[0] != n_ptr->active_links[1])); | ||
216 | } | ||
217 | |||
218 | int node_has_active_routes(struct node *n_ptr) | ||
219 | { | ||
220 | return (n_ptr && (n_ptr->last_router >= 0)); | ||
221 | } | ||
222 | |||
223 | int node_is_up(struct node *n_ptr) | ||
224 | { | ||
225 | return (node_has_active_links(n_ptr) || node_has_active_routes(n_ptr)); | ||
226 | } | ||
227 | |||
228 | struct node *node_attach_link(struct link *l_ptr) | ||
229 | { | ||
230 | struct node *n_ptr = node_find(l_ptr->addr); | ||
231 | |||
232 | if (!n_ptr) | ||
233 | n_ptr = node_create(l_ptr->addr); | ||
234 | if (n_ptr) { | ||
235 | u32 bearer_id = l_ptr->b_ptr->identity; | ||
236 | char addr_string[16]; | ||
237 | |||
238 | assert(bearer_id < MAX_BEARERS); | ||
239 | if (n_ptr->link_cnt >= 2) { | ||
240 | char addr_string[16]; | ||
241 | |||
242 | err("Attempt to create third link to %s\n", | ||
243 | addr_string_fill(addr_string, n_ptr->addr)); | ||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | if (!n_ptr->links[bearer_id]) { | ||
248 | n_ptr->links[bearer_id] = l_ptr; | ||
249 | net.zones[tipc_zone(l_ptr->addr)]->links++; | ||
250 | n_ptr->link_cnt++; | ||
251 | return n_ptr; | ||
252 | } | ||
253 | err("Attempt to establish second link on <%s> to <%s> \n", | ||
254 | l_ptr->b_ptr->publ.name, | ||
255 | addr_string_fill(addr_string, l_ptr->addr)); | ||
256 | } | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | void node_detach_link(struct node *n_ptr, struct link *l_ptr) | ||
261 | { | ||
262 | n_ptr->links[l_ptr->b_ptr->identity] = 0; | ||
263 | net.zones[tipc_zone(l_ptr->addr)]->links--; | ||
264 | n_ptr->link_cnt--; | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * Routing table management - five cases to handle: | ||
269 | * | ||
270 | * 1: A link towards a zone/cluster external node comes up. | ||
271 | * => Send a multicast message updating routing tables of all | ||
272 | * system nodes within own cluster that the new destination | ||
273 | * can be reached via this node. | ||
274 | * (node.establishedContact()=>cluster.multicastNewRoute()) | ||
275 | * | ||
276 | * 2: A link towards a slave node comes up. | ||
277 | * => Send a multicast message updating routing tables of all | ||
278 | * system nodes within own cluster that the new destination | ||
279 | * can be reached via this node. | ||
280 | * (node.establishedContact()=>cluster.multicastNewRoute()) | ||
281 | * => Send a message to the slave node about existence | ||
282 | * of all system nodes within cluster: | ||
283 | * (node.establishedContact()=>cluster.sendLocalRoutes()) | ||
284 | * | ||
285 | * 3: A new cluster local system node becomes available. | ||
286 | * => Send message(s) to this particular node containing | ||
287 | * information about all cluster external and slave | ||
288 | * nodes which can be reached via this node. | ||
289 | * (node.establishedContact()==>network.sendExternalRoutes()) | ||
290 | * (node.establishedContact()==>network.sendSlaveRoutes()) | ||
291 | * => Send messages to all directly connected slave nodes | ||
292 | * containing information about the existence of the new node | ||
293 | * (node.establishedContact()=>cluster.multicastNewRoute()) | ||
294 | * | ||
295 | * 4: The link towards a zone/cluster external node or slave | ||
296 | * node goes down. | ||
297 | * => Send a multcast message updating routing tables of all | ||
298 | * nodes within cluster that the new destination can not any | ||
299 | * longer be reached via this node. | ||
300 | * (node.lostAllLinks()=>cluster.bcastLostRoute()) | ||
301 | * | ||
302 | * 5: A cluster local system node becomes unavailable. | ||
303 | * => Remove all references to this node from the local | ||
304 | * routing tables. Note: This is a completely node | ||
305 | * local operation. | ||
306 | * (node.lostAllLinks()=>network.removeAsRouter()) | ||
307 | * => Send messages to all directly connected slave nodes | ||
308 | * containing information about loss of the node | ||
309 | * (node.establishedContact()=>cluster.multicastLostRoute()) | ||
310 | * | ||
311 | */ | ||
312 | |||
313 | static void node_established_contact(struct node *n_ptr) | ||
314 | { | ||
315 | struct cluster *c_ptr; | ||
316 | |||
317 | dbg("node_established_contact:-> %x\n", n_ptr->addr); | ||
318 | if (!node_has_active_routes(n_ptr)) { | ||
319 | k_signal((Handler)named_node_up, n_ptr->addr); | ||
320 | } | ||
321 | |||
322 | /* Syncronize broadcast acks */ | ||
323 | n_ptr->bclink.acked = bclink_get_last_sent(); | ||
324 | |||
325 | if (is_slave(tipc_own_addr)) | ||
326 | return; | ||
327 | if (!in_own_cluster(n_ptr->addr)) { | ||
328 | /* Usage case 1 (see above) */ | ||
329 | c_ptr = cluster_find(tipc_own_addr); | ||
330 | if (!c_ptr) | ||
331 | c_ptr = cluster_create(tipc_own_addr); | ||
332 | if (c_ptr) | ||
333 | cluster_bcast_new_route(c_ptr, n_ptr->addr, 1, | ||
334 | tipc_max_nodes); | ||
335 | return; | ||
336 | } | ||
337 | |||
338 | c_ptr = n_ptr->owner; | ||
339 | if (is_slave(n_ptr->addr)) { | ||
340 | /* Usage case 2 (see above) */ | ||
341 | cluster_bcast_new_route(c_ptr, n_ptr->addr, 1, tipc_max_nodes); | ||
342 | cluster_send_local_routes(c_ptr, n_ptr->addr); | ||
343 | return; | ||
344 | } | ||
345 | |||
346 | if (n_ptr->bclink.supported) { | ||
347 | nmap_add(&cluster_bcast_nodes, n_ptr->addr); | ||
348 | if (n_ptr->addr < tipc_own_addr) | ||
349 | tipc_own_tag++; | ||
350 | } | ||
351 | |||
352 | /* Case 3 (see above) */ | ||
353 | net_send_external_routes(n_ptr->addr); | ||
354 | cluster_send_slave_routes(c_ptr, n_ptr->addr); | ||
355 | cluster_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE, | ||
356 | highest_allowed_slave); | ||
357 | } | ||
358 | |||
359 | static void node_lost_contact(struct node *n_ptr) | ||
360 | { | ||
361 | struct cluster *c_ptr; | ||
362 | struct node_subscr *ns, *tns; | ||
363 | char addr_string[16]; | ||
364 | u32 i; | ||
365 | |||
366 | /* Clean up broadcast reception remains */ | ||
367 | n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0; | ||
368 | while (n_ptr->bclink.deferred_head) { | ||
369 | struct sk_buff* buf = n_ptr->bclink.deferred_head; | ||
370 | n_ptr->bclink.deferred_head = buf->next; | ||
371 | buf_discard(buf); | ||
372 | } | ||
373 | if (n_ptr->bclink.defragm) { | ||
374 | buf_discard(n_ptr->bclink.defragm); | ||
375 | n_ptr->bclink.defragm = NULL; | ||
376 | } | ||
377 | if (in_own_cluster(n_ptr->addr) && n_ptr->bclink.supported) { | ||
378 | bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000)); | ||
379 | } | ||
380 | |||
381 | /* Update routing tables */ | ||
382 | if (is_slave(tipc_own_addr)) { | ||
383 | net_remove_as_router(n_ptr->addr); | ||
384 | } else { | ||
385 | if (!in_own_cluster(n_ptr->addr)) { | ||
386 | /* Case 4 (see above) */ | ||
387 | c_ptr = cluster_find(tipc_own_addr); | ||
388 | cluster_bcast_lost_route(c_ptr, n_ptr->addr, 1, | ||
389 | tipc_max_nodes); | ||
390 | } else { | ||
391 | /* Case 5 (see above) */ | ||
392 | c_ptr = cluster_find(n_ptr->addr); | ||
393 | if (is_slave(n_ptr->addr)) { | ||
394 | cluster_bcast_lost_route(c_ptr, n_ptr->addr, 1, | ||
395 | tipc_max_nodes); | ||
396 | } else { | ||
397 | if (n_ptr->bclink.supported) { | ||
398 | nmap_remove(&cluster_bcast_nodes, | ||
399 | n_ptr->addr); | ||
400 | if (n_ptr->addr < tipc_own_addr) | ||
401 | tipc_own_tag--; | ||
402 | } | ||
403 | net_remove_as_router(n_ptr->addr); | ||
404 | cluster_bcast_lost_route(c_ptr, n_ptr->addr, | ||
405 | LOWEST_SLAVE, | ||
406 | highest_allowed_slave); | ||
407 | } | ||
408 | } | ||
409 | } | ||
410 | if (node_has_active_routes(n_ptr)) | ||
411 | return; | ||
412 | |||
413 | info("Lost contact with %s\n", | ||
414 | addr_string_fill(addr_string, n_ptr->addr)); | ||
415 | |||
416 | /* Abort link changeover */ | ||
417 | for (i = 0; i < MAX_BEARERS; i++) { | ||
418 | struct link *l_ptr = n_ptr->links[i]; | ||
419 | if (!l_ptr) | ||
420 | continue; | ||
421 | l_ptr->reset_checkpoint = l_ptr->next_in_no; | ||
422 | l_ptr->exp_msg_count = 0; | ||
423 | link_reset_fragments(l_ptr); | ||
424 | } | ||
425 | |||
426 | /* Notify subscribers */ | ||
427 | list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) { | ||
428 | ns->node = 0; | ||
429 | list_del_init(&ns->nodesub_list); | ||
430 | k_signal((Handler)ns->handle_node_down, | ||
431 | (unsigned long)ns->usr_handle); | ||
432 | } | ||
433 | } | ||
434 | |||
435 | /** | ||
436 | * node_select_next_hop - find the next-hop node for a message | ||
437 | * | ||
438 | * Called by when cluster local lookup has failed. | ||
439 | */ | ||
440 | |||
441 | struct node *node_select_next_hop(u32 addr, u32 selector) | ||
442 | { | ||
443 | struct node *n_ptr; | ||
444 | u32 router_addr; | ||
445 | |||
446 | if (!addr_domain_valid(addr)) | ||
447 | return 0; | ||
448 | |||
449 | /* Look for direct link to destination processsor */ | ||
450 | n_ptr = node_find(addr); | ||
451 | if (n_ptr && node_has_active_links(n_ptr)) | ||
452 | return n_ptr; | ||
453 | |||
454 | /* Cluster local system nodes *must* have direct links */ | ||
455 | if (!is_slave(addr) && in_own_cluster(addr)) | ||
456 | return 0; | ||
457 | |||
458 | /* Look for cluster local router with direct link to node */ | ||
459 | router_addr = node_select_router(n_ptr, selector); | ||
460 | if (router_addr) | ||
461 | return node_select(router_addr, selector); | ||
462 | |||
463 | /* Slave nodes can only be accessed within own cluster via a | ||
464 | known router with direct link -- if no router was found,give up */ | ||
465 | if (is_slave(addr)) | ||
466 | return 0; | ||
467 | |||
468 | /* Inter zone/cluster -- find any direct link to remote cluster */ | ||
469 | addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0); | ||
470 | n_ptr = net_select_remote_node(addr, selector); | ||
471 | if (n_ptr && node_has_active_links(n_ptr)) | ||
472 | return n_ptr; | ||
473 | |||
474 | /* Last resort -- look for any router to anywhere in remote zone */ | ||
475 | router_addr = net_select_router(addr, selector); | ||
476 | if (router_addr) | ||
477 | return node_select(router_addr, selector); | ||
478 | |||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | /** | ||
483 | * node_select_router - select router to reach specified node | ||
484 | * | ||
485 | * Uses a deterministic and fair algorithm for selecting router node. | ||
486 | */ | ||
487 | |||
488 | u32 node_select_router(struct node *n_ptr, u32 ref) | ||
489 | { | ||
490 | u32 ulim; | ||
491 | u32 mask; | ||
492 | u32 start; | ||
493 | u32 r; | ||
494 | |||
495 | if (!n_ptr) | ||
496 | return 0; | ||
497 | |||
498 | if (n_ptr->last_router < 0) | ||
499 | return 0; | ||
500 | ulim = ((n_ptr->last_router + 1) * 32) - 1; | ||
501 | |||
502 | /* Start entry must be random */ | ||
503 | mask = tipc_max_nodes; | ||
504 | while (mask > ulim) | ||
505 | mask >>= 1; | ||
506 | start = ref & mask; | ||
507 | r = start; | ||
508 | |||
509 | /* Lookup upwards with wrap-around */ | ||
510 | do { | ||
511 | if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1) | ||
512 | break; | ||
513 | } while (++r <= ulim); | ||
514 | if (r > ulim) { | ||
515 | r = 1; | ||
516 | do { | ||
517 | if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1) | ||
518 | break; | ||
519 | } while (++r < start); | ||
520 | assert(r != start); | ||
521 | } | ||
522 | assert(r && (r <= ulim)); | ||
523 | return tipc_addr(own_zone(), own_cluster(), r); | ||
524 | } | ||
525 | |||
526 | void node_add_router(struct node *n_ptr, u32 router) | ||
527 | { | ||
528 | u32 r_num = tipc_node(router); | ||
529 | |||
530 | n_ptr->routers[r_num / 32] = | ||
531 | ((1 << (r_num % 32)) | n_ptr->routers[r_num / 32]); | ||
532 | n_ptr->last_router = tipc_max_nodes / 32; | ||
533 | while ((--n_ptr->last_router >= 0) && | ||
534 | !n_ptr->routers[n_ptr->last_router]); | ||
535 | } | ||
536 | |||
537 | void node_remove_router(struct node *n_ptr, u32 router) | ||
538 | { | ||
539 | u32 r_num = tipc_node(router); | ||
540 | |||
541 | if (n_ptr->last_router < 0) | ||
542 | return; /* No routes */ | ||
543 | |||
544 | n_ptr->routers[r_num / 32] = | ||
545 | ((~(1 << (r_num % 32))) & (n_ptr->routers[r_num / 32])); | ||
546 | n_ptr->last_router = tipc_max_nodes / 32; | ||
547 | while ((--n_ptr->last_router >= 0) && | ||
548 | !n_ptr->routers[n_ptr->last_router]); | ||
549 | |||
550 | if (!node_is_up(n_ptr)) | ||
551 | node_lost_contact(n_ptr); | ||
552 | } | ||
553 | |||
554 | #if 0 | ||
555 | void node_print(struct print_buf *buf, struct node *n_ptr, char *str) | ||
556 | { | ||
557 | u32 i; | ||
558 | |||
559 | tipc_printf(buf, "\n\n%s", str); | ||
560 | for (i = 0; i < MAX_BEARERS; i++) { | ||
561 | if (!n_ptr->links[i]) | ||
562 | continue; | ||
563 | tipc_printf(buf, "Links[%u]: %x, ", i, n_ptr->links[i]); | ||
564 | } | ||
565 | tipc_printf(buf, "Active links: [%x,%x]\n", | ||
566 | n_ptr->active_links[0], n_ptr->active_links[1]); | ||
567 | } | ||
568 | #endif | ||
569 | |||
570 | u32 tipc_available_nodes(const u32 domain) | ||
571 | { | ||
572 | struct node *n_ptr; | ||
573 | u32 cnt = 0; | ||
574 | |||
575 | for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) { | ||
576 | if (!in_scope(domain, n_ptr->addr)) | ||
577 | continue; | ||
578 | if (node_is_up(n_ptr)) | ||
579 | cnt++; | ||
580 | } | ||
581 | return cnt; | ||
582 | } | ||
583 | |||
584 | struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space) | ||
585 | { | ||
586 | u32 domain; | ||
587 | struct sk_buff *buf; | ||
588 | struct node *n_ptr; | ||
589 | struct tipc_node_info node_info; | ||
590 | |||
591 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) | ||
592 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
593 | |||
594 | domain = *(u32 *)TLV_DATA(req_tlv_area); | ||
595 | domain = ntohl(domain); | ||
596 | if (!addr_domain_valid(domain)) | ||
597 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
598 | " (network address)"); | ||
599 | |||
600 | if (!nodes) | ||
601 | return cfg_reply_none(); | ||
602 | |||
603 | /* For now, get space for all other nodes | ||
604 | (will need to modify this when slave nodes are supported */ | ||
605 | |||
606 | buf = cfg_reply_alloc(TLV_SPACE(sizeof(node_info)) * | ||
607 | (tipc_max_nodes - 1)); | ||
608 | if (!buf) | ||
609 | return NULL; | ||
610 | |||
611 | /* Add TLVs for all nodes in scope */ | ||
612 | |||
613 | for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) { | ||
614 | if (!in_scope(domain, n_ptr->addr)) | ||
615 | continue; | ||
616 | node_info.addr = htonl(n_ptr->addr); | ||
617 | node_info.up = htonl(node_is_up(n_ptr)); | ||
618 | cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, | ||
619 | &node_info, sizeof(node_info)); | ||
620 | } | ||
621 | |||
622 | return buf; | ||
623 | } | ||
624 | |||
625 | struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space) | ||
626 | { | ||
627 | u32 domain; | ||
628 | struct sk_buff *buf; | ||
629 | struct node *n_ptr; | ||
630 | struct tipc_link_info link_info; | ||
631 | |||
632 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) | ||
633 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
634 | |||
635 | domain = *(u32 *)TLV_DATA(req_tlv_area); | ||
636 | domain = ntohl(domain); | ||
637 | if (!addr_domain_valid(domain)) | ||
638 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
639 | " (network address)"); | ||
640 | |||
641 | if (!nodes) | ||
642 | return cfg_reply_none(); | ||
643 | |||
644 | /* For now, get space for 2 links to all other nodes + bcast link | ||
645 | (will need to modify this when slave nodes are supported */ | ||
646 | |||
647 | buf = cfg_reply_alloc(TLV_SPACE(sizeof(link_info)) * | ||
648 | (2 * (tipc_max_nodes - 1) + 1)); | ||
649 | if (!buf) | ||
650 | return NULL; | ||
651 | |||
652 | /* Add TLV for broadcast link */ | ||
653 | |||
654 | link_info.dest = tipc_own_addr & 0xfffff00; | ||
655 | link_info.dest = htonl(link_info.dest); | ||
656 | link_info.up = htonl(1); | ||
657 | sprintf(link_info.str, bc_link_name); | ||
658 | cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); | ||
659 | |||
660 | /* Add TLVs for any other links in scope */ | ||
661 | |||
662 | for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) { | ||
663 | u32 i; | ||
664 | |||
665 | if (!in_scope(domain, n_ptr->addr)) | ||
666 | continue; | ||
667 | for (i = 0; i < MAX_BEARERS; i++) { | ||
668 | if (!n_ptr->links[i]) | ||
669 | continue; | ||
670 | link_info.dest = htonl(n_ptr->addr); | ||
671 | link_info.up = htonl(link_is_up(n_ptr->links[i])); | ||
672 | strcpy(link_info.str, n_ptr->links[i]->name); | ||
673 | cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, | ||
674 | &link_info, sizeof(link_info)); | ||
675 | } | ||
676 | } | ||
677 | |||
678 | return buf; | ||
679 | } | ||
diff --git a/net/tipc/node.h b/net/tipc/node.h new file mode 100644 index 000000000000..b39442badccf --- /dev/null +++ b/net/tipc/node.h | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * net/tipc/node.h: Include file for TIPC node management routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_NODE_H | ||
38 | #define _TIPC_NODE_H | ||
39 | |||
40 | #include "node_subscr.h" | ||
41 | #include "addr.h" | ||
42 | #include "cluster.h" | ||
43 | #include "bearer.h" | ||
44 | |||
45 | /** | ||
46 | * struct node - TIPC node structure | ||
47 | * @addr: network address of node | ||
48 | * @lock: spinlock governing access to structure | ||
49 | * @owner: pointer to cluster that node belongs to | ||
50 | * @next: pointer to next node in sorted list of cluster's nodes | ||
51 | * @nsub: list of "node down" subscriptions monitoring node | ||
52 | * @active_links: pointers to active links to node | ||
53 | * @links: pointers to all links to node | ||
54 | * @link_cnt: number of links to node | ||
55 | * @permit_changeover: non-zero if node has redundant links to this system | ||
56 | * @routers: bitmap (used for multicluster communication) | ||
57 | * @last_router: (used for multicluster communication) | ||
58 | * @bclink: broadcast-related info | ||
59 | * @supported: non-zero if node supports TIPC b'cast capability | ||
60 | * @acked: sequence # of last outbound b'cast message acknowledged by node | ||
61 | * @last_in: sequence # of last in-sequence b'cast message received from node | ||
62 | * @gap_after: sequence # of last message not requiring a NAK request | ||
63 | * @gap_to: sequence # of last message requiring a NAK request | ||
64 | * @nack_sync: counter that determines when NAK requests should be sent | ||
65 | * @deferred_head: oldest OOS b'cast message received from node | ||
66 | * @deferred_tail: newest OOS b'cast message received from node | ||
67 | * @defragm: list of partially reassembled b'cast message fragments from node | ||
68 | */ | ||
69 | |||
70 | struct node { | ||
71 | u32 addr; | ||
72 | spinlock_t lock; | ||
73 | struct cluster *owner; | ||
74 | struct node *next; | ||
75 | struct list_head nsub; | ||
76 | struct link *active_links[2]; | ||
77 | struct link *links[MAX_BEARERS]; | ||
78 | int link_cnt; | ||
79 | int permit_changeover; | ||
80 | u32 routers[512/32]; | ||
81 | int last_router; | ||
82 | struct { | ||
83 | int supported; | ||
84 | u32 acked; | ||
85 | u32 last_in; | ||
86 | u32 gap_after; | ||
87 | u32 gap_to; | ||
88 | u32 nack_sync; | ||
89 | struct sk_buff *deferred_head; | ||
90 | struct sk_buff *deferred_tail; | ||
91 | struct sk_buff *defragm; | ||
92 | } bclink; | ||
93 | }; | ||
94 | |||
95 | extern struct node *nodes; | ||
96 | extern u32 tipc_own_tag; | ||
97 | |||
98 | struct node *node_create(u32 addr); | ||
99 | void node_delete(struct node *n_ptr); | ||
100 | struct node *node_attach_link(struct link *l_ptr); | ||
101 | void node_detach_link(struct node *n_ptr, struct link *l_ptr); | ||
102 | void node_link_down(struct node *n_ptr, struct link *l_ptr); | ||
103 | void node_link_up(struct node *n_ptr, struct link *l_ptr); | ||
104 | int node_has_active_links(struct node *n_ptr); | ||
105 | int node_has_redundant_links(struct node *n_ptr); | ||
106 | u32 node_select_router(struct node *n_ptr, u32 ref); | ||
107 | struct node *node_select_next_hop(u32 addr, u32 selector); | ||
108 | int node_is_up(struct node *n_ptr); | ||
109 | void node_add_router(struct node *n_ptr, u32 router); | ||
110 | void node_remove_router(struct node *n_ptr, u32 router); | ||
111 | struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space); | ||
112 | struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space); | ||
113 | |||
114 | static inline struct node *node_find(u32 addr) | ||
115 | { | ||
116 | if (likely(in_own_cluster(addr))) | ||
117 | return local_nodes[tipc_node(addr)]; | ||
118 | else if (addr_domain_valid(addr)) { | ||
119 | struct cluster *c_ptr = cluster_find(addr); | ||
120 | |||
121 | if (c_ptr) | ||
122 | return c_ptr->nodes[tipc_node(addr)]; | ||
123 | } | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static inline struct node *node_select(u32 addr, u32 selector) | ||
128 | { | ||
129 | if (likely(in_own_cluster(addr))) | ||
130 | return local_nodes[tipc_node(addr)]; | ||
131 | return node_select_next_hop(addr, selector); | ||
132 | } | ||
133 | |||
134 | static inline void node_lock(struct node *n_ptr) | ||
135 | { | ||
136 | spin_lock_bh(&n_ptr->lock); | ||
137 | } | ||
138 | |||
139 | static inline void node_unlock(struct node *n_ptr) | ||
140 | { | ||
141 | spin_unlock_bh(&n_ptr->lock); | ||
142 | } | ||
143 | |||
144 | #endif | ||
diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c new file mode 100644 index 000000000000..79375927916f --- /dev/null +++ b/net/tipc/node_subscr.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * net/tipc/node_subscr.c: TIPC "node down" subscription handling | ||
3 | * | ||
4 | * Copyright (c) 1995-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "dbg.h" | ||
39 | #include "node_subscr.h" | ||
40 | #include "node.h" | ||
41 | #include "addr.h" | ||
42 | |||
43 | /** | ||
44 | * nodesub_subscribe - create "node down" subscription for specified node | ||
45 | */ | ||
46 | |||
47 | void nodesub_subscribe(struct node_subscr *node_sub, u32 addr, | ||
48 | void *usr_handle, net_ev_handler handle_down) | ||
49 | { | ||
50 | node_sub->node = 0; | ||
51 | if (addr == tipc_own_addr) | ||
52 | return; | ||
53 | if (!addr_node_valid(addr)) { | ||
54 | warn("node_subscr with illegal %x\n", addr); | ||
55 | return; | ||
56 | } | ||
57 | |||
58 | node_sub->handle_node_down = handle_down; | ||
59 | node_sub->usr_handle = usr_handle; | ||
60 | node_sub->node = node_find(addr); | ||
61 | assert(node_sub->node); | ||
62 | node_lock(node_sub->node); | ||
63 | list_add_tail(&node_sub->nodesub_list, &node_sub->node->nsub); | ||
64 | node_unlock(node_sub->node); | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * nodesub_unsubscribe - cancel "node down" subscription (if any) | ||
69 | */ | ||
70 | |||
71 | void nodesub_unsubscribe(struct node_subscr *node_sub) | ||
72 | { | ||
73 | if (!node_sub->node) | ||
74 | return; | ||
75 | |||
76 | node_lock(node_sub->node); | ||
77 | list_del_init(&node_sub->nodesub_list); | ||
78 | node_unlock(node_sub->node); | ||
79 | } | ||
diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h new file mode 100644 index 000000000000..a3b87ac4859b --- /dev/null +++ b/net/tipc/node_subscr.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * net/tipc/node_subscr.h: Include file for TIPC "node down" subscription handling | ||
3 | * | ||
4 | * Copyright (c) 1995-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_NODE_SUBSCR_H | ||
38 | #define _TIPC_NODE_SUBSCR_H | ||
39 | |||
40 | #include "addr.h" | ||
41 | |||
42 | typedef void (*net_ev_handler) (void *usr_handle); | ||
43 | |||
44 | /** | ||
45 | * struct node_subscr - "node down" subscription entry | ||
46 | * @node: ptr to node structure of interest (or NULL, if none) | ||
47 | * @handle_node_down: routine to invoke when node fails | ||
48 | * @usr_handle: argument to pass to routine when node fails | ||
49 | * @nodesub_list: adjacent entries in list of subscriptions for the node | ||
50 | */ | ||
51 | |||
52 | struct node_subscr { | ||
53 | struct node *node; | ||
54 | net_ev_handler handle_node_down; | ||
55 | void *usr_handle; | ||
56 | struct list_head nodesub_list; | ||
57 | }; | ||
58 | |||
59 | void nodesub_subscribe(struct node_subscr *node_sub, u32 addr, | ||
60 | void *usr_handle, net_ev_handler handle_down); | ||
61 | void nodesub_unsubscribe(struct node_subscr *node_sub); | ||
62 | |||
63 | #endif | ||
diff --git a/net/tipc/port.c b/net/tipc/port.c new file mode 100644 index 000000000000..66caca7abe92 --- /dev/null +++ b/net/tipc/port.c | |||
@@ -0,0 +1,1708 @@ | |||
1 | /* | ||
2 | * net/tipc/port.c: TIPC port code | ||
3 | * | ||
4 | * Copyright (c) 1992-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "config.h" | ||
39 | #include "dbg.h" | ||
40 | #include "port.h" | ||
41 | #include "addr.h" | ||
42 | #include "link.h" | ||
43 | #include "node.h" | ||
44 | #include "port.h" | ||
45 | #include "name_table.h" | ||
46 | #include "user_reg.h" | ||
47 | #include "msg.h" | ||
48 | #include "bcast.h" | ||
49 | |||
50 | /* Connection management: */ | ||
51 | #define PROBING_INTERVAL 3600000 /* [ms] => 1 h */ | ||
52 | #define CONFIRMED 0 | ||
53 | #define PROBING 1 | ||
54 | |||
55 | #define MAX_REJECT_SIZE 1024 | ||
56 | |||
57 | static struct sk_buff *msg_queue_head = 0; | ||
58 | static struct sk_buff *msg_queue_tail = 0; | ||
59 | |||
60 | spinlock_t port_list_lock = SPIN_LOCK_UNLOCKED; | ||
61 | static spinlock_t queue_lock = SPIN_LOCK_UNLOCKED; | ||
62 | |||
63 | LIST_HEAD(ports); | ||
64 | static void port_handle_node_down(unsigned long ref); | ||
65 | static struct sk_buff* port_build_self_abort_msg(struct port *,u32 err); | ||
66 | static struct sk_buff* port_build_peer_abort_msg(struct port *,u32 err); | ||
67 | static void port_timeout(unsigned long ref); | ||
68 | |||
69 | |||
70 | static inline u32 port_peernode(struct port *p_ptr) | ||
71 | { | ||
72 | return msg_destnode(&p_ptr->publ.phdr); | ||
73 | } | ||
74 | |||
75 | static inline u32 port_peerport(struct port *p_ptr) | ||
76 | { | ||
77 | return msg_destport(&p_ptr->publ.phdr); | ||
78 | } | ||
79 | |||
80 | static inline u32 port_out_seqno(struct port *p_ptr) | ||
81 | { | ||
82 | return msg_transp_seqno(&p_ptr->publ.phdr); | ||
83 | } | ||
84 | |||
85 | static inline void port_set_out_seqno(struct port *p_ptr, u32 seqno) | ||
86 | { | ||
87 | msg_set_transp_seqno(&p_ptr->publ.phdr,seqno); | ||
88 | } | ||
89 | |||
90 | static inline void port_incr_out_seqno(struct port *p_ptr) | ||
91 | { | ||
92 | struct tipc_msg *m = &p_ptr->publ.phdr; | ||
93 | |||
94 | if (likely(!msg_routed(m))) | ||
95 | return; | ||
96 | msg_set_transp_seqno(m, (msg_transp_seqno(m) + 1)); | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * tipc_multicast - send a multicast message to local and remote destinations | ||
101 | */ | ||
102 | |||
103 | int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, u32 domain, | ||
104 | u32 num_sect, struct iovec const *msg_sect) | ||
105 | { | ||
106 | struct tipc_msg *hdr; | ||
107 | struct sk_buff *buf; | ||
108 | struct sk_buff *ibuf = NULL; | ||
109 | struct port_list dports = {0, NULL, }; | ||
110 | struct port *oport = port_deref(ref); | ||
111 | int ext_targets; | ||
112 | int res; | ||
113 | |||
114 | if (unlikely(!oport)) | ||
115 | return -EINVAL; | ||
116 | |||
117 | /* Create multicast message */ | ||
118 | |||
119 | hdr = &oport->publ.phdr; | ||
120 | msg_set_type(hdr, TIPC_MCAST_MSG); | ||
121 | msg_set_nametype(hdr, seq->type); | ||
122 | msg_set_namelower(hdr, seq->lower); | ||
123 | msg_set_nameupper(hdr, seq->upper); | ||
124 | msg_set_hdr_sz(hdr, MCAST_H_SIZE); | ||
125 | res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, | ||
126 | !oport->user_port, &buf); | ||
127 | if (unlikely(!buf)) | ||
128 | return res; | ||
129 | |||
130 | /* Figure out where to send multicast message */ | ||
131 | |||
132 | ext_targets = nametbl_mc_translate(seq->type, seq->lower, seq->upper, | ||
133 | TIPC_NODE_SCOPE, &dports); | ||
134 | |||
135 | /* Send message to destinations (duplicate it only if necessary) */ | ||
136 | |||
137 | if (ext_targets) { | ||
138 | if (dports.count != 0) { | ||
139 | ibuf = skb_copy(buf, GFP_ATOMIC); | ||
140 | if (ibuf == NULL) { | ||
141 | port_list_free(&dports); | ||
142 | buf_discard(buf); | ||
143 | return -ENOMEM; | ||
144 | } | ||
145 | } | ||
146 | res = bclink_send_msg(buf); | ||
147 | if ((res < 0) && (dports.count != 0)) { | ||
148 | buf_discard(ibuf); | ||
149 | } | ||
150 | } else { | ||
151 | ibuf = buf; | ||
152 | } | ||
153 | |||
154 | if (res >= 0) { | ||
155 | if (ibuf) | ||
156 | port_recv_mcast(ibuf, &dports); | ||
157 | } else { | ||
158 | port_list_free(&dports); | ||
159 | } | ||
160 | return res; | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * port_recv_mcast - deliver multicast message to all destination ports | ||
165 | * | ||
166 | * If there is no port list, perform a lookup to create one | ||
167 | */ | ||
168 | |||
169 | void port_recv_mcast(struct sk_buff *buf, struct port_list *dp) | ||
170 | { | ||
171 | struct tipc_msg* msg; | ||
172 | struct port_list dports = {0, NULL, }; | ||
173 | struct port_list *item = dp; | ||
174 | int cnt = 0; | ||
175 | |||
176 | assert(buf); | ||
177 | msg = buf_msg(buf); | ||
178 | |||
179 | /* Create destination port list, if one wasn't supplied */ | ||
180 | |||
181 | if (dp == NULL) { | ||
182 | nametbl_mc_translate(msg_nametype(msg), | ||
183 | msg_namelower(msg), | ||
184 | msg_nameupper(msg), | ||
185 | TIPC_CLUSTER_SCOPE, | ||
186 | &dports); | ||
187 | item = dp = &dports; | ||
188 | } | ||
189 | |||
190 | /* Deliver a copy of message to each destination port */ | ||
191 | |||
192 | if (dp->count != 0) { | ||
193 | if (dp->count == 1) { | ||
194 | msg_set_destport(msg, dp->ports[0]); | ||
195 | port_recv_msg(buf); | ||
196 | port_list_free(dp); | ||
197 | return; | ||
198 | } | ||
199 | for (; cnt < dp->count; cnt++) { | ||
200 | int index = cnt % PLSIZE; | ||
201 | struct sk_buff *b = skb_clone(buf, GFP_ATOMIC); | ||
202 | |||
203 | if (b == NULL) { | ||
204 | warn("Buffer allocation failure\n"); | ||
205 | msg_dbg(msg, "LOST:"); | ||
206 | goto exit; | ||
207 | } | ||
208 | if ((index == 0) && (cnt != 0)) { | ||
209 | item = item->next; | ||
210 | } | ||
211 | msg_set_destport(buf_msg(b),item->ports[index]); | ||
212 | port_recv_msg(b); | ||
213 | } | ||
214 | } | ||
215 | exit: | ||
216 | buf_discard(buf); | ||
217 | port_list_free(dp); | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * tipc_createport_raw - create a native TIPC port | ||
222 | * | ||
223 | * Returns local port reference | ||
224 | */ | ||
225 | |||
226 | u32 tipc_createport_raw(void *usr_handle, | ||
227 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), | ||
228 | void (*wakeup)(struct tipc_port *), | ||
229 | const u32 importance) | ||
230 | { | ||
231 | struct port *p_ptr; | ||
232 | struct tipc_msg *msg; | ||
233 | u32 ref; | ||
234 | |||
235 | p_ptr = kmalloc(sizeof(*p_ptr), GFP_ATOMIC); | ||
236 | if (p_ptr == NULL) { | ||
237 | warn("Memory squeeze; failed to create port\n"); | ||
238 | return 0; | ||
239 | } | ||
240 | memset(p_ptr, 0, sizeof(*p_ptr)); | ||
241 | ref = ref_acquire(p_ptr, &p_ptr->publ.lock); | ||
242 | if (!ref) { | ||
243 | warn("Reference Table Exhausted\n"); | ||
244 | kfree(p_ptr); | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | port_lock(ref); | ||
249 | p_ptr->publ.ref = ref; | ||
250 | msg = &p_ptr->publ.phdr; | ||
251 | msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0); | ||
252 | msg_set_orignode(msg, tipc_own_addr); | ||
253 | msg_set_prevnode(msg, tipc_own_addr); | ||
254 | msg_set_origport(msg, ref); | ||
255 | msg_set_importance(msg,importance); | ||
256 | p_ptr->last_in_seqno = 41; | ||
257 | p_ptr->sent = 1; | ||
258 | p_ptr->publ.usr_handle = usr_handle; | ||
259 | INIT_LIST_HEAD(&p_ptr->wait_list); | ||
260 | INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); | ||
261 | p_ptr->congested_link = 0; | ||
262 | p_ptr->max_pkt = MAX_PKT_DEFAULT; | ||
263 | p_ptr->dispatcher = dispatcher; | ||
264 | p_ptr->wakeup = wakeup; | ||
265 | p_ptr->user_port = 0; | ||
266 | k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref); | ||
267 | spin_lock_bh(&port_list_lock); | ||
268 | INIT_LIST_HEAD(&p_ptr->publications); | ||
269 | INIT_LIST_HEAD(&p_ptr->port_list); | ||
270 | list_add_tail(&p_ptr->port_list, &ports); | ||
271 | spin_unlock_bh(&port_list_lock); | ||
272 | port_unlock(p_ptr); | ||
273 | return ref; | ||
274 | } | ||
275 | |||
276 | int tipc_deleteport(u32 ref) | ||
277 | { | ||
278 | struct port *p_ptr; | ||
279 | struct sk_buff *buf = 0; | ||
280 | |||
281 | tipc_withdraw(ref, 0, 0); | ||
282 | p_ptr = port_lock(ref); | ||
283 | if (!p_ptr) | ||
284 | return -EINVAL; | ||
285 | |||
286 | ref_discard(ref); | ||
287 | port_unlock(p_ptr); | ||
288 | |||
289 | k_cancel_timer(&p_ptr->timer); | ||
290 | if (p_ptr->publ.connected) { | ||
291 | buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT); | ||
292 | nodesub_unsubscribe(&p_ptr->subscription); | ||
293 | } | ||
294 | if (p_ptr->user_port) { | ||
295 | reg_remove_port(p_ptr->user_port); | ||
296 | kfree(p_ptr->user_port); | ||
297 | } | ||
298 | |||
299 | spin_lock_bh(&port_list_lock); | ||
300 | list_del(&p_ptr->port_list); | ||
301 | list_del(&p_ptr->wait_list); | ||
302 | spin_unlock_bh(&port_list_lock); | ||
303 | k_term_timer(&p_ptr->timer); | ||
304 | kfree(p_ptr); | ||
305 | dbg("Deleted port %u\n", ref); | ||
306 | net_route_msg(buf); | ||
307 | return TIPC_OK; | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * tipc_get_port() - return port associated with 'ref' | ||
312 | * | ||
313 | * Note: Port is not locked. | ||
314 | */ | ||
315 | |||
316 | struct tipc_port *tipc_get_port(const u32 ref) | ||
317 | { | ||
318 | return (struct tipc_port *)ref_deref(ref); | ||
319 | } | ||
320 | |||
321 | /** | ||
322 | * tipc_get_handle - return user handle associated to port 'ref' | ||
323 | */ | ||
324 | |||
325 | void *tipc_get_handle(const u32 ref) | ||
326 | { | ||
327 | struct port *p_ptr; | ||
328 | void * handle; | ||
329 | |||
330 | p_ptr = port_lock(ref); | ||
331 | if (!p_ptr) | ||
332 | return 0; | ||
333 | handle = p_ptr->publ.usr_handle; | ||
334 | port_unlock(p_ptr); | ||
335 | return handle; | ||
336 | } | ||
337 | |||
338 | static inline int port_unreliable(struct port *p_ptr) | ||
339 | { | ||
340 | return msg_src_droppable(&p_ptr->publ.phdr); | ||
341 | } | ||
342 | |||
343 | int tipc_portunreliable(u32 ref, unsigned int *isunreliable) | ||
344 | { | ||
345 | struct port *p_ptr; | ||
346 | |||
347 | p_ptr = port_lock(ref); | ||
348 | if (!p_ptr) | ||
349 | return -EINVAL; | ||
350 | *isunreliable = port_unreliable(p_ptr); | ||
351 | spin_unlock_bh(p_ptr->publ.lock); | ||
352 | return TIPC_OK; | ||
353 | } | ||
354 | |||
355 | int tipc_set_portunreliable(u32 ref, unsigned int isunreliable) | ||
356 | { | ||
357 | struct port *p_ptr; | ||
358 | |||
359 | p_ptr = port_lock(ref); | ||
360 | if (!p_ptr) | ||
361 | return -EINVAL; | ||
362 | msg_set_src_droppable(&p_ptr->publ.phdr, (isunreliable != 0)); | ||
363 | port_unlock(p_ptr); | ||
364 | return TIPC_OK; | ||
365 | } | ||
366 | |||
367 | static inline int port_unreturnable(struct port *p_ptr) | ||
368 | { | ||
369 | return msg_dest_droppable(&p_ptr->publ.phdr); | ||
370 | } | ||
371 | |||
372 | int tipc_portunreturnable(u32 ref, unsigned int *isunrejectable) | ||
373 | { | ||
374 | struct port *p_ptr; | ||
375 | |||
376 | p_ptr = port_lock(ref); | ||
377 | if (!p_ptr) | ||
378 | return -EINVAL; | ||
379 | *isunrejectable = port_unreturnable(p_ptr); | ||
380 | spin_unlock_bh(p_ptr->publ.lock); | ||
381 | return TIPC_OK; | ||
382 | } | ||
383 | |||
384 | int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable) | ||
385 | { | ||
386 | struct port *p_ptr; | ||
387 | |||
388 | p_ptr = port_lock(ref); | ||
389 | if (!p_ptr) | ||
390 | return -EINVAL; | ||
391 | msg_set_dest_droppable(&p_ptr->publ.phdr, (isunrejectable != 0)); | ||
392 | port_unlock(p_ptr); | ||
393 | return TIPC_OK; | ||
394 | } | ||
395 | |||
396 | /* | ||
397 | * port_build_proto_msg(): build a port level protocol | ||
398 | * or a connection abortion message. Called with | ||
399 | * tipc_port lock on. | ||
400 | */ | ||
401 | static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode, | ||
402 | u32 origport, u32 orignode, | ||
403 | u32 usr, u32 type, u32 err, | ||
404 | u32 seqno, u32 ack) | ||
405 | { | ||
406 | struct sk_buff *buf; | ||
407 | struct tipc_msg *msg; | ||
408 | |||
409 | buf = buf_acquire(LONG_H_SIZE); | ||
410 | if (buf) { | ||
411 | msg = buf_msg(buf); | ||
412 | msg_init(msg, usr, type, err, LONG_H_SIZE, destnode); | ||
413 | msg_set_destport(msg, destport); | ||
414 | msg_set_origport(msg, origport); | ||
415 | msg_set_destnode(msg, destnode); | ||
416 | msg_set_orignode(msg, orignode); | ||
417 | msg_set_transp_seqno(msg, seqno); | ||
418 | msg_set_msgcnt(msg, ack); | ||
419 | msg_dbg(msg, "PORT>SEND>:"); | ||
420 | } | ||
421 | return buf; | ||
422 | } | ||
423 | |||
424 | int tipc_set_msg_option(struct tipc_port *tp_ptr, const char *opt, const u32 sz) | ||
425 | { | ||
426 | msg_expand(&tp_ptr->phdr, msg_destnode(&tp_ptr->phdr)); | ||
427 | msg_set_options(&tp_ptr->phdr, opt, sz); | ||
428 | return TIPC_OK; | ||
429 | } | ||
430 | |||
431 | int tipc_reject_msg(struct sk_buff *buf, u32 err) | ||
432 | { | ||
433 | struct tipc_msg *msg = buf_msg(buf); | ||
434 | struct sk_buff *rbuf; | ||
435 | struct tipc_msg *rmsg; | ||
436 | int hdr_sz; | ||
437 | u32 imp = msg_importance(msg); | ||
438 | u32 data_sz = msg_data_sz(msg); | ||
439 | |||
440 | if (data_sz > MAX_REJECT_SIZE) | ||
441 | data_sz = MAX_REJECT_SIZE; | ||
442 | if (msg_connected(msg) && (imp < TIPC_CRITICAL_IMPORTANCE)) | ||
443 | imp++; | ||
444 | msg_dbg(msg, "port->rej: "); | ||
445 | |||
446 | /* discard rejected message if it shouldn't be returned to sender */ | ||
447 | if (msg_errcode(msg) || msg_dest_droppable(msg)) { | ||
448 | buf_discard(buf); | ||
449 | return data_sz; | ||
450 | } | ||
451 | |||
452 | /* construct rejected message */ | ||
453 | if (msg_mcast(msg)) | ||
454 | hdr_sz = MCAST_H_SIZE; | ||
455 | else | ||
456 | hdr_sz = LONG_H_SIZE; | ||
457 | rbuf = buf_acquire(data_sz + hdr_sz); | ||
458 | if (rbuf == NULL) { | ||
459 | buf_discard(buf); | ||
460 | return data_sz; | ||
461 | } | ||
462 | rmsg = buf_msg(rbuf); | ||
463 | msg_init(rmsg, imp, msg_type(msg), err, hdr_sz, msg_orignode(msg)); | ||
464 | msg_set_destport(rmsg, msg_origport(msg)); | ||
465 | msg_set_prevnode(rmsg, tipc_own_addr); | ||
466 | msg_set_origport(rmsg, msg_destport(msg)); | ||
467 | if (msg_short(msg)) | ||
468 | msg_set_orignode(rmsg, tipc_own_addr); | ||
469 | else | ||
470 | msg_set_orignode(rmsg, msg_destnode(msg)); | ||
471 | msg_set_size(rmsg, data_sz + hdr_sz); | ||
472 | msg_set_nametype(rmsg, msg_nametype(msg)); | ||
473 | msg_set_nameinst(rmsg, msg_nameinst(msg)); | ||
474 | memcpy(rbuf->data + hdr_sz, msg_data(msg), data_sz); | ||
475 | |||
476 | /* send self-abort message when rejecting on a connected port */ | ||
477 | if (msg_connected(msg)) { | ||
478 | struct sk_buff *abuf = 0; | ||
479 | struct port *p_ptr = port_lock(msg_destport(msg)); | ||
480 | |||
481 | if (p_ptr) { | ||
482 | if (p_ptr->publ.connected) | ||
483 | abuf = port_build_self_abort_msg(p_ptr, err); | ||
484 | port_unlock(p_ptr); | ||
485 | } | ||
486 | net_route_msg(abuf); | ||
487 | } | ||
488 | |||
489 | /* send rejected message */ | ||
490 | buf_discard(buf); | ||
491 | net_route_msg(rbuf); | ||
492 | return data_sz; | ||
493 | } | ||
494 | |||
495 | int port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, | ||
496 | struct iovec const *msg_sect, u32 num_sect, | ||
497 | int err) | ||
498 | { | ||
499 | struct sk_buff *buf; | ||
500 | int res; | ||
501 | |||
502 | res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, | ||
503 | !p_ptr->user_port, &buf); | ||
504 | if (!buf) | ||
505 | return res; | ||
506 | |||
507 | return tipc_reject_msg(buf, err); | ||
508 | } | ||
509 | |||
510 | static void port_timeout(unsigned long ref) | ||
511 | { | ||
512 | struct port *p_ptr = port_lock(ref); | ||
513 | struct sk_buff *buf = 0; | ||
514 | |||
515 | if (!p_ptr || !p_ptr->publ.connected) | ||
516 | return; | ||
517 | |||
518 | /* Last probe answered ? */ | ||
519 | if (p_ptr->probing_state == PROBING) { | ||
520 | buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT); | ||
521 | } else { | ||
522 | buf = port_build_proto_msg(port_peerport(p_ptr), | ||
523 | port_peernode(p_ptr), | ||
524 | p_ptr->publ.ref, | ||
525 | tipc_own_addr, | ||
526 | CONN_MANAGER, | ||
527 | CONN_PROBE, | ||
528 | TIPC_OK, | ||
529 | port_out_seqno(p_ptr), | ||
530 | 0); | ||
531 | port_incr_out_seqno(p_ptr); | ||
532 | p_ptr->probing_state = PROBING; | ||
533 | k_start_timer(&p_ptr->timer, p_ptr->probing_interval); | ||
534 | } | ||
535 | port_unlock(p_ptr); | ||
536 | net_route_msg(buf); | ||
537 | } | ||
538 | |||
539 | |||
540 | static void port_handle_node_down(unsigned long ref) | ||
541 | { | ||
542 | struct port *p_ptr = port_lock(ref); | ||
543 | struct sk_buff* buf = 0; | ||
544 | |||
545 | if (!p_ptr) | ||
546 | return; | ||
547 | buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_NODE); | ||
548 | port_unlock(p_ptr); | ||
549 | net_route_msg(buf); | ||
550 | } | ||
551 | |||
552 | |||
553 | static struct sk_buff *port_build_self_abort_msg(struct port *p_ptr, u32 err) | ||
554 | { | ||
555 | u32 imp = msg_importance(&p_ptr->publ.phdr); | ||
556 | |||
557 | if (!p_ptr->publ.connected) | ||
558 | return 0; | ||
559 | if (imp < TIPC_CRITICAL_IMPORTANCE) | ||
560 | imp++; | ||
561 | return port_build_proto_msg(p_ptr->publ.ref, | ||
562 | tipc_own_addr, | ||
563 | port_peerport(p_ptr), | ||
564 | port_peernode(p_ptr), | ||
565 | imp, | ||
566 | TIPC_CONN_MSG, | ||
567 | err, | ||
568 | p_ptr->last_in_seqno + 1, | ||
569 | 0); | ||
570 | } | ||
571 | |||
572 | |||
573 | static struct sk_buff *port_build_peer_abort_msg(struct port *p_ptr, u32 err) | ||
574 | { | ||
575 | u32 imp = msg_importance(&p_ptr->publ.phdr); | ||
576 | |||
577 | if (!p_ptr->publ.connected) | ||
578 | return 0; | ||
579 | if (imp < TIPC_CRITICAL_IMPORTANCE) | ||
580 | imp++; | ||
581 | return port_build_proto_msg(port_peerport(p_ptr), | ||
582 | port_peernode(p_ptr), | ||
583 | p_ptr->publ.ref, | ||
584 | tipc_own_addr, | ||
585 | imp, | ||
586 | TIPC_CONN_MSG, | ||
587 | err, | ||
588 | port_out_seqno(p_ptr), | ||
589 | 0); | ||
590 | } | ||
591 | |||
592 | void port_recv_proto_msg(struct sk_buff *buf) | ||
593 | { | ||
594 | struct tipc_msg *msg = buf_msg(buf); | ||
595 | struct port *p_ptr = port_lock(msg_destport(msg)); | ||
596 | u32 err = TIPC_OK; | ||
597 | struct sk_buff *r_buf = 0; | ||
598 | struct sk_buff *abort_buf = 0; | ||
599 | |||
600 | msg_dbg(msg, "PORT<RECV<:"); | ||
601 | |||
602 | if (!p_ptr) { | ||
603 | err = TIPC_ERR_NO_PORT; | ||
604 | } else if (p_ptr->publ.connected) { | ||
605 | if (port_peernode(p_ptr) != msg_orignode(msg)) | ||
606 | err = TIPC_ERR_NO_PORT; | ||
607 | if (port_peerport(p_ptr) != msg_origport(msg)) | ||
608 | err = TIPC_ERR_NO_PORT; | ||
609 | if (!err && msg_routed(msg)) { | ||
610 | u32 seqno = msg_transp_seqno(msg); | ||
611 | u32 myno = ++p_ptr->last_in_seqno; | ||
612 | if (seqno != myno) { | ||
613 | err = TIPC_ERR_NO_PORT; | ||
614 | abort_buf = port_build_self_abort_msg(p_ptr, err); | ||
615 | } | ||
616 | } | ||
617 | if (msg_type(msg) == CONN_ACK) { | ||
618 | int wakeup = port_congested(p_ptr) && | ||
619 | p_ptr->publ.congested && | ||
620 | p_ptr->wakeup; | ||
621 | p_ptr->acked += msg_msgcnt(msg); | ||
622 | if (port_congested(p_ptr)) | ||
623 | goto exit; | ||
624 | p_ptr->publ.congested = 0; | ||
625 | if (!wakeup) | ||
626 | goto exit; | ||
627 | p_ptr->wakeup(&p_ptr->publ); | ||
628 | goto exit; | ||
629 | } | ||
630 | } else if (p_ptr->publ.published) { | ||
631 | err = TIPC_ERR_NO_PORT; | ||
632 | } | ||
633 | if (err) { | ||
634 | r_buf = port_build_proto_msg(msg_origport(msg), | ||
635 | msg_orignode(msg), | ||
636 | msg_destport(msg), | ||
637 | tipc_own_addr, | ||
638 | DATA_HIGH, | ||
639 | TIPC_CONN_MSG, | ||
640 | err, | ||
641 | 0, | ||
642 | 0); | ||
643 | goto exit; | ||
644 | } | ||
645 | |||
646 | /* All is fine */ | ||
647 | if (msg_type(msg) == CONN_PROBE) { | ||
648 | r_buf = port_build_proto_msg(msg_origport(msg), | ||
649 | msg_orignode(msg), | ||
650 | msg_destport(msg), | ||
651 | tipc_own_addr, | ||
652 | CONN_MANAGER, | ||
653 | CONN_PROBE_REPLY, | ||
654 | TIPC_OK, | ||
655 | port_out_seqno(p_ptr), | ||
656 | 0); | ||
657 | } | ||
658 | p_ptr->probing_state = CONFIRMED; | ||
659 | port_incr_out_seqno(p_ptr); | ||
660 | exit: | ||
661 | if (p_ptr) | ||
662 | port_unlock(p_ptr); | ||
663 | net_route_msg(r_buf); | ||
664 | net_route_msg(abort_buf); | ||
665 | buf_discard(buf); | ||
666 | } | ||
667 | |||
668 | static void port_print(struct port *p_ptr, struct print_buf *buf, int full_id) | ||
669 | { | ||
670 | struct publication *publ; | ||
671 | |||
672 | if (full_id) | ||
673 | tipc_printf(buf, "<%u.%u.%u:%u>:", | ||
674 | tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), | ||
675 | tipc_node(tipc_own_addr), p_ptr->publ.ref); | ||
676 | else | ||
677 | tipc_printf(buf, "%-10u:", p_ptr->publ.ref); | ||
678 | |||
679 | if (p_ptr->publ.connected) { | ||
680 | u32 dport = port_peerport(p_ptr); | ||
681 | u32 destnode = port_peernode(p_ptr); | ||
682 | |||
683 | tipc_printf(buf, " connected to <%u.%u.%u:%u>", | ||
684 | tipc_zone(destnode), tipc_cluster(destnode), | ||
685 | tipc_node(destnode), dport); | ||
686 | if (p_ptr->publ.conn_type != 0) | ||
687 | tipc_printf(buf, " via {%u,%u}", | ||
688 | p_ptr->publ.conn_type, | ||
689 | p_ptr->publ.conn_instance); | ||
690 | } | ||
691 | else if (p_ptr->publ.published) { | ||
692 | tipc_printf(buf, " bound to"); | ||
693 | list_for_each_entry(publ, &p_ptr->publications, pport_list) { | ||
694 | if (publ->lower == publ->upper) | ||
695 | tipc_printf(buf, " {%u,%u}", publ->type, | ||
696 | publ->lower); | ||
697 | else | ||
698 | tipc_printf(buf, " {%u,%u,%u}", publ->type, | ||
699 | publ->lower, publ->upper); | ||
700 | } | ||
701 | } | ||
702 | tipc_printf(buf, "\n"); | ||
703 | } | ||
704 | |||
705 | #define MAX_PORT_QUERY 32768 | ||
706 | |||
707 | struct sk_buff *port_get_ports(void) | ||
708 | { | ||
709 | struct sk_buff *buf; | ||
710 | struct tlv_desc *rep_tlv; | ||
711 | struct print_buf pb; | ||
712 | struct port *p_ptr; | ||
713 | int str_len; | ||
714 | |||
715 | buf = cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY)); | ||
716 | if (!buf) | ||
717 | return NULL; | ||
718 | rep_tlv = (struct tlv_desc *)buf->data; | ||
719 | |||
720 | printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY); | ||
721 | spin_lock_bh(&port_list_lock); | ||
722 | list_for_each_entry(p_ptr, &ports, port_list) { | ||
723 | spin_lock_bh(p_ptr->publ.lock); | ||
724 | port_print(p_ptr, &pb, 0); | ||
725 | spin_unlock_bh(p_ptr->publ.lock); | ||
726 | } | ||
727 | spin_unlock_bh(&port_list_lock); | ||
728 | str_len = printbuf_validate(&pb); | ||
729 | |||
730 | skb_put(buf, TLV_SPACE(str_len)); | ||
731 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | ||
732 | |||
733 | return buf; | ||
734 | } | ||
735 | |||
736 | #if 0 | ||
737 | |||
738 | #define MAX_PORT_STATS 2000 | ||
739 | |||
740 | struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space) | ||
741 | { | ||
742 | u32 ref; | ||
743 | struct port *p_ptr; | ||
744 | struct sk_buff *buf; | ||
745 | struct tlv_desc *rep_tlv; | ||
746 | struct print_buf pb; | ||
747 | int str_len; | ||
748 | |||
749 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_PORT_REF)) | ||
750 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
751 | |||
752 | ref = *(u32 *)TLV_DATA(req_tlv_area); | ||
753 | ref = ntohl(ref); | ||
754 | |||
755 | p_ptr = port_lock(ref); | ||
756 | if (!p_ptr) | ||
757 | return cfg_reply_error_string("port not found"); | ||
758 | |||
759 | buf = cfg_reply_alloc(TLV_SPACE(MAX_PORT_STATS)); | ||
760 | if (!buf) { | ||
761 | port_unlock(p_ptr); | ||
762 | return NULL; | ||
763 | } | ||
764 | rep_tlv = (struct tlv_desc *)buf->data; | ||
765 | |||
766 | printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_STATS); | ||
767 | port_print(p_ptr, &pb, 1); | ||
768 | /* NEED TO FILL IN ADDITIONAL PORT STATISTICS HERE */ | ||
769 | port_unlock(p_ptr); | ||
770 | str_len = printbuf_validate(&pb); | ||
771 | |||
772 | skb_put(buf, TLV_SPACE(str_len)); | ||
773 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | ||
774 | |||
775 | return buf; | ||
776 | } | ||
777 | |||
778 | #endif | ||
779 | |||
780 | void port_reinit(void) | ||
781 | { | ||
782 | struct port *p_ptr; | ||
783 | struct tipc_msg *msg; | ||
784 | |||
785 | spin_lock_bh(&port_list_lock); | ||
786 | list_for_each_entry(p_ptr, &ports, port_list) { | ||
787 | msg = &p_ptr->publ.phdr; | ||
788 | if (msg_orignode(msg) == tipc_own_addr) | ||
789 | break; | ||
790 | msg_set_orignode(msg, tipc_own_addr); | ||
791 | } | ||
792 | spin_unlock_bh(&port_list_lock); | ||
793 | } | ||
794 | |||
795 | |||
796 | /* | ||
797 | * port_dispatcher_sigh(): Signal handler for messages destinated | ||
798 | * to the tipc_port interface. | ||
799 | */ | ||
800 | |||
801 | static void port_dispatcher_sigh(void *dummy) | ||
802 | { | ||
803 | struct sk_buff *buf; | ||
804 | |||
805 | spin_lock_bh(&queue_lock); | ||
806 | buf = msg_queue_head; | ||
807 | msg_queue_head = 0; | ||
808 | spin_unlock_bh(&queue_lock); | ||
809 | |||
810 | while (buf) { | ||
811 | struct port *p_ptr; | ||
812 | struct user_port *up_ptr; | ||
813 | struct tipc_portid orig; | ||
814 | struct tipc_name_seq dseq; | ||
815 | void *usr_handle; | ||
816 | int connected; | ||
817 | int published; | ||
818 | |||
819 | struct sk_buff *next = buf->next; | ||
820 | struct tipc_msg *msg = buf_msg(buf); | ||
821 | u32 dref = msg_destport(msg); | ||
822 | |||
823 | p_ptr = port_lock(dref); | ||
824 | if (!p_ptr) { | ||
825 | /* Port deleted while msg in queue */ | ||
826 | tipc_reject_msg(buf, TIPC_ERR_NO_PORT); | ||
827 | buf = next; | ||
828 | continue; | ||
829 | } | ||
830 | orig.ref = msg_origport(msg); | ||
831 | orig.node = msg_orignode(msg); | ||
832 | up_ptr = p_ptr->user_port; | ||
833 | usr_handle = up_ptr->usr_handle; | ||
834 | connected = p_ptr->publ.connected; | ||
835 | published = p_ptr->publ.published; | ||
836 | |||
837 | if (unlikely(msg_errcode(msg))) | ||
838 | goto err; | ||
839 | |||
840 | switch (msg_type(msg)) { | ||
841 | |||
842 | case TIPC_CONN_MSG:{ | ||
843 | tipc_conn_msg_event cb = up_ptr->conn_msg_cb; | ||
844 | u32 peer_port = port_peerport(p_ptr); | ||
845 | u32 peer_node = port_peernode(p_ptr); | ||
846 | |||
847 | spin_unlock_bh(p_ptr->publ.lock); | ||
848 | if (unlikely(!connected)) { | ||
849 | if (unlikely(published)) | ||
850 | goto reject; | ||
851 | tipc_connect2port(dref,&orig); | ||
852 | } | ||
853 | if (unlikely(msg_origport(msg) != peer_port)) | ||
854 | goto reject; | ||
855 | if (unlikely(msg_orignode(msg) != peer_node)) | ||
856 | goto reject; | ||
857 | if (unlikely(!cb)) | ||
858 | goto reject; | ||
859 | if (unlikely(++p_ptr->publ.conn_unacked >= | ||
860 | TIPC_FLOW_CONTROL_WIN)) | ||
861 | tipc_acknowledge(dref, | ||
862 | p_ptr->publ.conn_unacked); | ||
863 | skb_pull(buf, msg_hdr_sz(msg)); | ||
864 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
865 | msg_data_sz(msg)); | ||
866 | break; | ||
867 | } | ||
868 | case TIPC_DIRECT_MSG:{ | ||
869 | tipc_msg_event cb = up_ptr->msg_cb; | ||
870 | |||
871 | spin_unlock_bh(p_ptr->publ.lock); | ||
872 | if (unlikely(connected)) | ||
873 | goto reject; | ||
874 | if (unlikely(!cb)) | ||
875 | goto reject; | ||
876 | skb_pull(buf, msg_hdr_sz(msg)); | ||
877 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
878 | msg_data_sz(msg), msg_importance(msg), | ||
879 | &orig); | ||
880 | break; | ||
881 | } | ||
882 | case TIPC_NAMED_MSG:{ | ||
883 | tipc_named_msg_event cb = up_ptr->named_msg_cb; | ||
884 | |||
885 | spin_unlock_bh(p_ptr->publ.lock); | ||
886 | if (unlikely(connected)) | ||
887 | goto reject; | ||
888 | if (unlikely(!cb)) | ||
889 | goto reject; | ||
890 | if (unlikely(!published)) | ||
891 | goto reject; | ||
892 | dseq.type = msg_nametype(msg); | ||
893 | dseq.lower = msg_nameinst(msg); | ||
894 | dseq.upper = dseq.lower; | ||
895 | skb_pull(buf, msg_hdr_sz(msg)); | ||
896 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
897 | msg_data_sz(msg), msg_importance(msg), | ||
898 | &orig, &dseq); | ||
899 | break; | ||
900 | } | ||
901 | } | ||
902 | if (buf) | ||
903 | buf_discard(buf); | ||
904 | buf = next; | ||
905 | continue; | ||
906 | err: | ||
907 | switch (msg_type(msg)) { | ||
908 | |||
909 | case TIPC_CONN_MSG:{ | ||
910 | tipc_conn_shutdown_event cb = | ||
911 | up_ptr->conn_err_cb; | ||
912 | u32 peer_port = port_peerport(p_ptr); | ||
913 | u32 peer_node = port_peernode(p_ptr); | ||
914 | |||
915 | spin_unlock_bh(p_ptr->publ.lock); | ||
916 | if (!connected || !cb) | ||
917 | break; | ||
918 | if (msg_origport(msg) != peer_port) | ||
919 | break; | ||
920 | if (msg_orignode(msg) != peer_node) | ||
921 | break; | ||
922 | tipc_disconnect(dref); | ||
923 | skb_pull(buf, msg_hdr_sz(msg)); | ||
924 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
925 | msg_data_sz(msg), msg_errcode(msg)); | ||
926 | break; | ||
927 | } | ||
928 | case TIPC_DIRECT_MSG:{ | ||
929 | tipc_msg_err_event cb = up_ptr->err_cb; | ||
930 | |||
931 | spin_unlock_bh(p_ptr->publ.lock); | ||
932 | if (connected || !cb) | ||
933 | break; | ||
934 | skb_pull(buf, msg_hdr_sz(msg)); | ||
935 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
936 | msg_data_sz(msg), msg_errcode(msg), &orig); | ||
937 | break; | ||
938 | } | ||
939 | case TIPC_NAMED_MSG:{ | ||
940 | tipc_named_msg_err_event cb = | ||
941 | up_ptr->named_err_cb; | ||
942 | |||
943 | spin_unlock_bh(p_ptr->publ.lock); | ||
944 | if (connected || !cb) | ||
945 | break; | ||
946 | dseq.type = msg_nametype(msg); | ||
947 | dseq.lower = msg_nameinst(msg); | ||
948 | dseq.upper = dseq.lower; | ||
949 | skb_pull(buf, msg_hdr_sz(msg)); | ||
950 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
951 | msg_data_sz(msg), msg_errcode(msg), &dseq); | ||
952 | break; | ||
953 | } | ||
954 | } | ||
955 | if (buf) | ||
956 | buf_discard(buf); | ||
957 | buf = next; | ||
958 | continue; | ||
959 | reject: | ||
960 | tipc_reject_msg(buf, TIPC_ERR_NO_PORT); | ||
961 | buf = next; | ||
962 | } | ||
963 | } | ||
964 | |||
965 | /* | ||
966 | * port_dispatcher(): Dispatcher for messages destinated | ||
967 | * to the tipc_port interface. Called with port locked. | ||
968 | */ | ||
969 | |||
970 | static u32 port_dispatcher(struct tipc_port *dummy, struct sk_buff *buf) | ||
971 | { | ||
972 | buf->next = NULL; | ||
973 | spin_lock_bh(&queue_lock); | ||
974 | if (msg_queue_head) { | ||
975 | msg_queue_tail->next = buf; | ||
976 | msg_queue_tail = buf; | ||
977 | } else { | ||
978 | msg_queue_tail = msg_queue_head = buf; | ||
979 | k_signal((Handler)port_dispatcher_sigh, 0); | ||
980 | } | ||
981 | spin_unlock_bh(&queue_lock); | ||
982 | return TIPC_OK; | ||
983 | } | ||
984 | |||
985 | /* | ||
986 | * Wake up port after congestion: Called with port locked, | ||
987 | * | ||
988 | */ | ||
989 | |||
990 | static void port_wakeup_sh(unsigned long ref) | ||
991 | { | ||
992 | struct port *p_ptr; | ||
993 | struct user_port *up_ptr; | ||
994 | tipc_continue_event cb = 0; | ||
995 | void *uh = 0; | ||
996 | |||
997 | p_ptr = port_lock(ref); | ||
998 | if (p_ptr) { | ||
999 | up_ptr = p_ptr->user_port; | ||
1000 | if (up_ptr) { | ||
1001 | cb = up_ptr->continue_event_cb; | ||
1002 | uh = up_ptr->usr_handle; | ||
1003 | } | ||
1004 | port_unlock(p_ptr); | ||
1005 | } | ||
1006 | if (cb) | ||
1007 | cb(uh, ref); | ||
1008 | } | ||
1009 | |||
1010 | |||
1011 | static void port_wakeup(struct tipc_port *p_ptr) | ||
1012 | { | ||
1013 | k_signal((Handler)port_wakeup_sh, p_ptr->ref); | ||
1014 | } | ||
1015 | |||
1016 | void tipc_acknowledge(u32 ref, u32 ack) | ||
1017 | { | ||
1018 | struct port *p_ptr; | ||
1019 | struct sk_buff *buf = 0; | ||
1020 | |||
1021 | p_ptr = port_lock(ref); | ||
1022 | if (!p_ptr) | ||
1023 | return; | ||
1024 | if (p_ptr->publ.connected) { | ||
1025 | p_ptr->publ.conn_unacked -= ack; | ||
1026 | buf = port_build_proto_msg(port_peerport(p_ptr), | ||
1027 | port_peernode(p_ptr), | ||
1028 | ref, | ||
1029 | tipc_own_addr, | ||
1030 | CONN_MANAGER, | ||
1031 | CONN_ACK, | ||
1032 | TIPC_OK, | ||
1033 | port_out_seqno(p_ptr), | ||
1034 | ack); | ||
1035 | } | ||
1036 | port_unlock(p_ptr); | ||
1037 | net_route_msg(buf); | ||
1038 | } | ||
1039 | |||
1040 | /* | ||
1041 | * tipc_createport(): user level call. Will add port to | ||
1042 | * registry if non-zero user_ref. | ||
1043 | */ | ||
1044 | |||
1045 | int tipc_createport(u32 user_ref, | ||
1046 | void *usr_handle, | ||
1047 | unsigned int importance, | ||
1048 | tipc_msg_err_event error_cb, | ||
1049 | tipc_named_msg_err_event named_error_cb, | ||
1050 | tipc_conn_shutdown_event conn_error_cb, | ||
1051 | tipc_msg_event msg_cb, | ||
1052 | tipc_named_msg_event named_msg_cb, | ||
1053 | tipc_conn_msg_event conn_msg_cb, | ||
1054 | tipc_continue_event continue_event_cb,/* May be zero */ | ||
1055 | u32 *portref) | ||
1056 | { | ||
1057 | struct user_port *up_ptr; | ||
1058 | struct port *p_ptr; | ||
1059 | u32 ref; | ||
1060 | |||
1061 | up_ptr = (struct user_port *)kmalloc(sizeof(*up_ptr), GFP_ATOMIC); | ||
1062 | if (up_ptr == NULL) { | ||
1063 | return -ENOMEM; | ||
1064 | } | ||
1065 | ref = tipc_createport_raw(0, port_dispatcher, port_wakeup, importance); | ||
1066 | p_ptr = port_lock(ref); | ||
1067 | if (!p_ptr) { | ||
1068 | kfree(up_ptr); | ||
1069 | return -ENOMEM; | ||
1070 | } | ||
1071 | |||
1072 | p_ptr->user_port = up_ptr; | ||
1073 | up_ptr->user_ref = user_ref; | ||
1074 | up_ptr->usr_handle = usr_handle; | ||
1075 | up_ptr->ref = p_ptr->publ.ref; | ||
1076 | up_ptr->err_cb = error_cb; | ||
1077 | up_ptr->named_err_cb = named_error_cb; | ||
1078 | up_ptr->conn_err_cb = conn_error_cb; | ||
1079 | up_ptr->msg_cb = msg_cb; | ||
1080 | up_ptr->named_msg_cb = named_msg_cb; | ||
1081 | up_ptr->conn_msg_cb = conn_msg_cb; | ||
1082 | up_ptr->continue_event_cb = continue_event_cb; | ||
1083 | INIT_LIST_HEAD(&up_ptr->uport_list); | ||
1084 | reg_add_port(up_ptr); | ||
1085 | *portref = p_ptr->publ.ref; | ||
1086 | dbg(" tipc_createport: %x with ref %u\n", p_ptr, p_ptr->publ.ref); | ||
1087 | port_unlock(p_ptr); | ||
1088 | return TIPC_OK; | ||
1089 | } | ||
1090 | |||
1091 | int tipc_ownidentity(u32 ref, struct tipc_portid *id) | ||
1092 | { | ||
1093 | id->ref = ref; | ||
1094 | id->node = tipc_own_addr; | ||
1095 | return TIPC_OK; | ||
1096 | } | ||
1097 | |||
1098 | int tipc_portimportance(u32 ref, unsigned int *importance) | ||
1099 | { | ||
1100 | struct port *p_ptr; | ||
1101 | |||
1102 | p_ptr = port_lock(ref); | ||
1103 | if (!p_ptr) | ||
1104 | return -EINVAL; | ||
1105 | *importance = (unsigned int)msg_importance(&p_ptr->publ.phdr); | ||
1106 | spin_unlock_bh(p_ptr->publ.lock); | ||
1107 | return TIPC_OK; | ||
1108 | } | ||
1109 | |||
1110 | int tipc_set_portimportance(u32 ref, unsigned int imp) | ||
1111 | { | ||
1112 | struct port *p_ptr; | ||
1113 | |||
1114 | if (imp > TIPC_CRITICAL_IMPORTANCE) | ||
1115 | return -EINVAL; | ||
1116 | |||
1117 | p_ptr = port_lock(ref); | ||
1118 | if (!p_ptr) | ||
1119 | return -EINVAL; | ||
1120 | msg_set_importance(&p_ptr->publ.phdr, (u32)imp); | ||
1121 | spin_unlock_bh(p_ptr->publ.lock); | ||
1122 | return TIPC_OK; | ||
1123 | } | ||
1124 | |||
1125 | |||
1126 | int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) | ||
1127 | { | ||
1128 | struct port *p_ptr; | ||
1129 | struct publication *publ; | ||
1130 | u32 key; | ||
1131 | int res = -EINVAL; | ||
1132 | |||
1133 | p_ptr = port_lock(ref); | ||
1134 | dbg("tipc_publ %u, p_ptr = %x, conn = %x, scope = %x, " | ||
1135 | "lower = %u, upper = %u\n", | ||
1136 | ref, p_ptr, p_ptr->publ.connected, scope, seq->lower, seq->upper); | ||
1137 | if (!p_ptr) | ||
1138 | return -EINVAL; | ||
1139 | if (p_ptr->publ.connected) | ||
1140 | goto exit; | ||
1141 | if (seq->lower > seq->upper) | ||
1142 | goto exit; | ||
1143 | if ((scope < TIPC_ZONE_SCOPE) || (scope > TIPC_NODE_SCOPE)) | ||
1144 | goto exit; | ||
1145 | key = ref + p_ptr->pub_count + 1; | ||
1146 | if (key == ref) { | ||
1147 | res = -EADDRINUSE; | ||
1148 | goto exit; | ||
1149 | } | ||
1150 | publ = nametbl_publish(seq->type, seq->lower, seq->upper, | ||
1151 | scope, p_ptr->publ.ref, key); | ||
1152 | if (publ) { | ||
1153 | list_add(&publ->pport_list, &p_ptr->publications); | ||
1154 | p_ptr->pub_count++; | ||
1155 | p_ptr->publ.published = 1; | ||
1156 | res = TIPC_OK; | ||
1157 | } | ||
1158 | exit: | ||
1159 | port_unlock(p_ptr); | ||
1160 | return res; | ||
1161 | } | ||
1162 | |||
1163 | int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) | ||
1164 | { | ||
1165 | struct port *p_ptr; | ||
1166 | struct publication *publ; | ||
1167 | struct publication *tpubl; | ||
1168 | int res = -EINVAL; | ||
1169 | |||
1170 | p_ptr = port_lock(ref); | ||
1171 | if (!p_ptr) | ||
1172 | return -EINVAL; | ||
1173 | if (!p_ptr->publ.published) | ||
1174 | goto exit; | ||
1175 | if (!seq) { | ||
1176 | list_for_each_entry_safe(publ, tpubl, | ||
1177 | &p_ptr->publications, pport_list) { | ||
1178 | nametbl_withdraw(publ->type, publ->lower, | ||
1179 | publ->ref, publ->key); | ||
1180 | } | ||
1181 | res = TIPC_OK; | ||
1182 | } else { | ||
1183 | list_for_each_entry_safe(publ, tpubl, | ||
1184 | &p_ptr->publications, pport_list) { | ||
1185 | if (publ->scope != scope) | ||
1186 | continue; | ||
1187 | if (publ->type != seq->type) | ||
1188 | continue; | ||
1189 | if (publ->lower != seq->lower) | ||
1190 | continue; | ||
1191 | if (publ->upper != seq->upper) | ||
1192 | break; | ||
1193 | nametbl_withdraw(publ->type, publ->lower, | ||
1194 | publ->ref, publ->key); | ||
1195 | res = TIPC_OK; | ||
1196 | break; | ||
1197 | } | ||
1198 | } | ||
1199 | if (list_empty(&p_ptr->publications)) | ||
1200 | p_ptr->publ.published = 0; | ||
1201 | exit: | ||
1202 | port_unlock(p_ptr); | ||
1203 | return res; | ||
1204 | } | ||
1205 | |||
1206 | int tipc_connect2port(u32 ref, struct tipc_portid const *peer) | ||
1207 | { | ||
1208 | struct port *p_ptr; | ||
1209 | struct tipc_msg *msg; | ||
1210 | int res = -EINVAL; | ||
1211 | |||
1212 | p_ptr = port_lock(ref); | ||
1213 | if (!p_ptr) | ||
1214 | return -EINVAL; | ||
1215 | if (p_ptr->publ.published || p_ptr->publ.connected) | ||
1216 | goto exit; | ||
1217 | if (!peer->ref) | ||
1218 | goto exit; | ||
1219 | |||
1220 | msg = &p_ptr->publ.phdr; | ||
1221 | msg_set_destnode(msg, peer->node); | ||
1222 | msg_set_destport(msg, peer->ref); | ||
1223 | msg_set_orignode(msg, tipc_own_addr); | ||
1224 | msg_set_origport(msg, p_ptr->publ.ref); | ||
1225 | msg_set_transp_seqno(msg, 42); | ||
1226 | msg_set_type(msg, TIPC_CONN_MSG); | ||
1227 | if (!may_route(peer->node)) | ||
1228 | msg_set_hdr_sz(msg, SHORT_H_SIZE); | ||
1229 | else | ||
1230 | msg_set_hdr_sz(msg, LONG_H_SIZE); | ||
1231 | |||
1232 | p_ptr->probing_interval = PROBING_INTERVAL; | ||
1233 | p_ptr->probing_state = CONFIRMED; | ||
1234 | p_ptr->publ.connected = 1; | ||
1235 | k_start_timer(&p_ptr->timer, p_ptr->probing_interval); | ||
1236 | |||
1237 | nodesub_subscribe(&p_ptr->subscription,peer->node, | ||
1238 | (void *)(unsigned long)ref, | ||
1239 | (net_ev_handler)port_handle_node_down); | ||
1240 | res = TIPC_OK; | ||
1241 | exit: | ||
1242 | port_unlock(p_ptr); | ||
1243 | p_ptr->max_pkt = link_get_max_pkt(peer->node, ref); | ||
1244 | return res; | ||
1245 | } | ||
1246 | |||
1247 | /* | ||
1248 | * tipc_disconnect(): Disconnect port form peer. | ||
1249 | * This is a node local operation. | ||
1250 | */ | ||
1251 | |||
1252 | int tipc_disconnect(u32 ref) | ||
1253 | { | ||
1254 | struct port *p_ptr; | ||
1255 | int res = -ENOTCONN; | ||
1256 | |||
1257 | p_ptr = port_lock(ref); | ||
1258 | if (!p_ptr) | ||
1259 | return -EINVAL; | ||
1260 | if (p_ptr->publ.connected) { | ||
1261 | p_ptr->publ.connected = 0; | ||
1262 | /* let timer expire on it's own to avoid deadlock! */ | ||
1263 | nodesub_unsubscribe(&p_ptr->subscription); | ||
1264 | res = TIPC_OK; | ||
1265 | } | ||
1266 | port_unlock(p_ptr); | ||
1267 | return res; | ||
1268 | } | ||
1269 | |||
1270 | /* | ||
1271 | * tipc_shutdown(): Send a SHUTDOWN msg to peer and disconnect | ||
1272 | */ | ||
1273 | int tipc_shutdown(u32 ref) | ||
1274 | { | ||
1275 | struct port *p_ptr; | ||
1276 | struct sk_buff *buf = 0; | ||
1277 | |||
1278 | p_ptr = port_lock(ref); | ||
1279 | if (!p_ptr) | ||
1280 | return -EINVAL; | ||
1281 | |||
1282 | if (p_ptr->publ.connected) { | ||
1283 | u32 imp = msg_importance(&p_ptr->publ.phdr); | ||
1284 | if (imp < TIPC_CRITICAL_IMPORTANCE) | ||
1285 | imp++; | ||
1286 | buf = port_build_proto_msg(port_peerport(p_ptr), | ||
1287 | port_peernode(p_ptr), | ||
1288 | ref, | ||
1289 | tipc_own_addr, | ||
1290 | imp, | ||
1291 | TIPC_CONN_MSG, | ||
1292 | TIPC_CONN_SHUTDOWN, | ||
1293 | port_out_seqno(p_ptr), | ||
1294 | 0); | ||
1295 | } | ||
1296 | port_unlock(p_ptr); | ||
1297 | net_route_msg(buf); | ||
1298 | return tipc_disconnect(ref); | ||
1299 | } | ||
1300 | |||
1301 | int tipc_isconnected(u32 ref, int *isconnected) | ||
1302 | { | ||
1303 | struct port *p_ptr; | ||
1304 | |||
1305 | p_ptr = port_lock(ref); | ||
1306 | if (!p_ptr) | ||
1307 | return -EINVAL; | ||
1308 | *isconnected = p_ptr->publ.connected; | ||
1309 | port_unlock(p_ptr); | ||
1310 | return TIPC_OK; | ||
1311 | } | ||
1312 | |||
1313 | int tipc_peer(u32 ref, struct tipc_portid *peer) | ||
1314 | { | ||
1315 | struct port *p_ptr; | ||
1316 | int res; | ||
1317 | |||
1318 | p_ptr = port_lock(ref); | ||
1319 | if (!p_ptr) | ||
1320 | return -EINVAL; | ||
1321 | if (p_ptr->publ.connected) { | ||
1322 | peer->ref = port_peerport(p_ptr); | ||
1323 | peer->node = port_peernode(p_ptr); | ||
1324 | res = TIPC_OK; | ||
1325 | } else | ||
1326 | res = -ENOTCONN; | ||
1327 | port_unlock(p_ptr); | ||
1328 | return res; | ||
1329 | } | ||
1330 | |||
1331 | int tipc_ref_valid(u32 ref) | ||
1332 | { | ||
1333 | /* Works irrespective of type */ | ||
1334 | return !!ref_deref(ref); | ||
1335 | } | ||
1336 | |||
1337 | |||
1338 | /* | ||
1339 | * port_recv_sections(): Concatenate and deliver sectioned | ||
1340 | * message for this node. | ||
1341 | */ | ||
1342 | |||
1343 | int port_recv_sections(struct port *sender, unsigned int num_sect, | ||
1344 | struct iovec const *msg_sect) | ||
1345 | { | ||
1346 | struct sk_buff *buf; | ||
1347 | int res; | ||
1348 | |||
1349 | res = msg_build(&sender->publ.phdr, msg_sect, num_sect, | ||
1350 | MAX_MSG_SIZE, !sender->user_port, &buf); | ||
1351 | if (likely(buf)) | ||
1352 | port_recv_msg(buf); | ||
1353 | return res; | ||
1354 | } | ||
1355 | |||
1356 | /** | ||
1357 | * tipc_send - send message sections on connection | ||
1358 | */ | ||
1359 | |||
1360 | int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) | ||
1361 | { | ||
1362 | struct port *p_ptr; | ||
1363 | u32 destnode; | ||
1364 | int res; | ||
1365 | |||
1366 | p_ptr = port_deref(ref); | ||
1367 | if (!p_ptr || !p_ptr->publ.connected) | ||
1368 | return -EINVAL; | ||
1369 | |||
1370 | p_ptr->publ.congested = 1; | ||
1371 | if (!port_congested(p_ptr)) { | ||
1372 | destnode = port_peernode(p_ptr); | ||
1373 | if (likely(destnode != tipc_own_addr)) | ||
1374 | res = link_send_sections_fast(p_ptr, msg_sect, num_sect, | ||
1375 | destnode); | ||
1376 | else | ||
1377 | res = port_recv_sections(p_ptr, num_sect, msg_sect); | ||
1378 | |||
1379 | if (likely(res != -ELINKCONG)) { | ||
1380 | port_incr_out_seqno(p_ptr); | ||
1381 | p_ptr->publ.congested = 0; | ||
1382 | p_ptr->sent++; | ||
1383 | return res; | ||
1384 | } | ||
1385 | } | ||
1386 | if (port_unreliable(p_ptr)) { | ||
1387 | p_ptr->publ.congested = 0; | ||
1388 | /* Just calculate msg length and return */ | ||
1389 | return msg_calc_data_size(msg_sect, num_sect); | ||
1390 | } | ||
1391 | return -ELINKCONG; | ||
1392 | } | ||
1393 | |||
1394 | /** | ||
1395 | * tipc_send_buf - send message buffer on connection | ||
1396 | */ | ||
1397 | |||
1398 | int tipc_send_buf(u32 ref, struct sk_buff *buf, unsigned int dsz) | ||
1399 | { | ||
1400 | struct port *p_ptr; | ||
1401 | struct tipc_msg *msg; | ||
1402 | u32 destnode; | ||
1403 | u32 hsz; | ||
1404 | u32 sz; | ||
1405 | u32 res; | ||
1406 | |||
1407 | p_ptr = port_deref(ref); | ||
1408 | if (!p_ptr || !p_ptr->publ.connected) | ||
1409 | return -EINVAL; | ||
1410 | |||
1411 | msg = &p_ptr->publ.phdr; | ||
1412 | hsz = msg_hdr_sz(msg); | ||
1413 | sz = hsz + dsz; | ||
1414 | msg_set_size(msg, sz); | ||
1415 | if (skb_cow(buf, hsz)) | ||
1416 | return -ENOMEM; | ||
1417 | |||
1418 | skb_push(buf, hsz); | ||
1419 | memcpy(buf->data, (unchar *)msg, hsz); | ||
1420 | destnode = msg_destnode(msg); | ||
1421 | p_ptr->publ.congested = 1; | ||
1422 | if (!port_congested(p_ptr)) { | ||
1423 | if (likely(destnode != tipc_own_addr)) | ||
1424 | res = tipc_send_buf_fast(buf, destnode); | ||
1425 | else { | ||
1426 | port_recv_msg(buf); | ||
1427 | res = sz; | ||
1428 | } | ||
1429 | if (likely(res != -ELINKCONG)) { | ||
1430 | port_incr_out_seqno(p_ptr); | ||
1431 | p_ptr->sent++; | ||
1432 | p_ptr->publ.congested = 0; | ||
1433 | return res; | ||
1434 | } | ||
1435 | } | ||
1436 | if (port_unreliable(p_ptr)) { | ||
1437 | p_ptr->publ.congested = 0; | ||
1438 | return dsz; | ||
1439 | } | ||
1440 | return -ELINKCONG; | ||
1441 | } | ||
1442 | |||
1443 | /** | ||
1444 | * tipc_forward2name - forward message sections to port name | ||
1445 | */ | ||
1446 | |||
1447 | int tipc_forward2name(u32 ref, | ||
1448 | struct tipc_name const *name, | ||
1449 | u32 domain, | ||
1450 | u32 num_sect, | ||
1451 | struct iovec const *msg_sect, | ||
1452 | struct tipc_portid const *orig, | ||
1453 | unsigned int importance) | ||
1454 | { | ||
1455 | struct port *p_ptr; | ||
1456 | struct tipc_msg *msg; | ||
1457 | u32 destnode = domain; | ||
1458 | u32 destport = 0; | ||
1459 | int res; | ||
1460 | |||
1461 | p_ptr = port_deref(ref); | ||
1462 | if (!p_ptr || p_ptr->publ.connected) | ||
1463 | return -EINVAL; | ||
1464 | |||
1465 | msg = &p_ptr->publ.phdr; | ||
1466 | msg_set_type(msg, TIPC_NAMED_MSG); | ||
1467 | msg_set_orignode(msg, orig->node); | ||
1468 | msg_set_origport(msg, orig->ref); | ||
1469 | msg_set_hdr_sz(msg, LONG_H_SIZE); | ||
1470 | msg_set_nametype(msg, name->type); | ||
1471 | msg_set_nameinst(msg, name->instance); | ||
1472 | msg_set_lookup_scope(msg, addr_scope(domain)); | ||
1473 | if (importance <= TIPC_CRITICAL_IMPORTANCE) | ||
1474 | msg_set_importance(msg,importance); | ||
1475 | destport = nametbl_translate(name->type, name->instance, &destnode); | ||
1476 | msg_set_destnode(msg, destnode); | ||
1477 | msg_set_destport(msg, destport); | ||
1478 | |||
1479 | if (likely(destport || destnode)) { | ||
1480 | p_ptr->sent++; | ||
1481 | if (likely(destnode == tipc_own_addr)) | ||
1482 | return port_recv_sections(p_ptr, num_sect, msg_sect); | ||
1483 | res = link_send_sections_fast(p_ptr, msg_sect, num_sect, | ||
1484 | destnode); | ||
1485 | if (likely(res != -ELINKCONG)) | ||
1486 | return res; | ||
1487 | if (port_unreliable(p_ptr)) { | ||
1488 | /* Just calculate msg length and return */ | ||
1489 | return msg_calc_data_size(msg_sect, num_sect); | ||
1490 | } | ||
1491 | return -ELINKCONG; | ||
1492 | } | ||
1493 | return port_reject_sections(p_ptr, msg, msg_sect, num_sect, | ||
1494 | TIPC_ERR_NO_NAME); | ||
1495 | } | ||
1496 | |||
1497 | /** | ||
1498 | * tipc_send2name - send message sections to port name | ||
1499 | */ | ||
1500 | |||
1501 | int tipc_send2name(u32 ref, | ||
1502 | struct tipc_name const *name, | ||
1503 | unsigned int domain, | ||
1504 | unsigned int num_sect, | ||
1505 | struct iovec const *msg_sect) | ||
1506 | { | ||
1507 | struct tipc_portid orig; | ||
1508 | |||
1509 | orig.ref = ref; | ||
1510 | orig.node = tipc_own_addr; | ||
1511 | return tipc_forward2name(ref, name, domain, num_sect, msg_sect, &orig, | ||
1512 | TIPC_PORT_IMPORTANCE); | ||
1513 | } | ||
1514 | |||
1515 | /** | ||
1516 | * tipc_forward_buf2name - forward message buffer to port name | ||
1517 | */ | ||
1518 | |||
1519 | int tipc_forward_buf2name(u32 ref, | ||
1520 | struct tipc_name const *name, | ||
1521 | u32 domain, | ||
1522 | struct sk_buff *buf, | ||
1523 | unsigned int dsz, | ||
1524 | struct tipc_portid const *orig, | ||
1525 | unsigned int importance) | ||
1526 | { | ||
1527 | struct port *p_ptr; | ||
1528 | struct tipc_msg *msg; | ||
1529 | u32 destnode = domain; | ||
1530 | u32 destport = 0; | ||
1531 | int res; | ||
1532 | |||
1533 | p_ptr = (struct port *)ref_deref(ref); | ||
1534 | if (!p_ptr || p_ptr->publ.connected) | ||
1535 | return -EINVAL; | ||
1536 | |||
1537 | msg = &p_ptr->publ.phdr; | ||
1538 | if (importance <= TIPC_CRITICAL_IMPORTANCE) | ||
1539 | msg_set_importance(msg, importance); | ||
1540 | msg_set_type(msg, TIPC_NAMED_MSG); | ||
1541 | msg_set_orignode(msg, orig->node); | ||
1542 | msg_set_origport(msg, orig->ref); | ||
1543 | msg_set_nametype(msg, name->type); | ||
1544 | msg_set_nameinst(msg, name->instance); | ||
1545 | msg_set_lookup_scope(msg, addr_scope(domain)); | ||
1546 | msg_set_hdr_sz(msg, LONG_H_SIZE); | ||
1547 | msg_set_size(msg, LONG_H_SIZE + dsz); | ||
1548 | destport = nametbl_translate(name->type, name->instance, &destnode); | ||
1549 | msg_set_destnode(msg, destnode); | ||
1550 | msg_set_destport(msg, destport); | ||
1551 | msg_dbg(msg, "forw2name ==> "); | ||
1552 | if (skb_cow(buf, LONG_H_SIZE)) | ||
1553 | return -ENOMEM; | ||
1554 | skb_push(buf, LONG_H_SIZE); | ||
1555 | memcpy(buf->data, (unchar *)msg, LONG_H_SIZE); | ||
1556 | msg_dbg(buf_msg(buf),"PREP:"); | ||
1557 | if (likely(destport || destnode)) { | ||
1558 | p_ptr->sent++; | ||
1559 | if (destnode == tipc_own_addr) | ||
1560 | return port_recv_msg(buf); | ||
1561 | res = tipc_send_buf_fast(buf, destnode); | ||
1562 | if (likely(res != -ELINKCONG)) | ||
1563 | return res; | ||
1564 | if (port_unreliable(p_ptr)) | ||
1565 | return dsz; | ||
1566 | return -ELINKCONG; | ||
1567 | } | ||
1568 | return tipc_reject_msg(buf, TIPC_ERR_NO_NAME); | ||
1569 | } | ||
1570 | |||
1571 | /** | ||
1572 | * tipc_send_buf2name - send message buffer to port name | ||
1573 | */ | ||
1574 | |||
1575 | int tipc_send_buf2name(u32 ref, | ||
1576 | struct tipc_name const *dest, | ||
1577 | u32 domain, | ||
1578 | struct sk_buff *buf, | ||
1579 | unsigned int dsz) | ||
1580 | { | ||
1581 | struct tipc_portid orig; | ||
1582 | |||
1583 | orig.ref = ref; | ||
1584 | orig.node = tipc_own_addr; | ||
1585 | return tipc_forward_buf2name(ref, dest, domain, buf, dsz, &orig, | ||
1586 | TIPC_PORT_IMPORTANCE); | ||
1587 | } | ||
1588 | |||
1589 | /** | ||
1590 | * tipc_forward2port - forward message sections to port identity | ||
1591 | */ | ||
1592 | |||
1593 | int tipc_forward2port(u32 ref, | ||
1594 | struct tipc_portid const *dest, | ||
1595 | unsigned int num_sect, | ||
1596 | struct iovec const *msg_sect, | ||
1597 | struct tipc_portid const *orig, | ||
1598 | unsigned int importance) | ||
1599 | { | ||
1600 | struct port *p_ptr; | ||
1601 | struct tipc_msg *msg; | ||
1602 | int res; | ||
1603 | |||
1604 | p_ptr = port_deref(ref); | ||
1605 | if (!p_ptr || p_ptr->publ.connected) | ||
1606 | return -EINVAL; | ||
1607 | |||
1608 | msg = &p_ptr->publ.phdr; | ||
1609 | msg_set_type(msg, TIPC_DIRECT_MSG); | ||
1610 | msg_set_orignode(msg, orig->node); | ||
1611 | msg_set_origport(msg, orig->ref); | ||
1612 | msg_set_destnode(msg, dest->node); | ||
1613 | msg_set_destport(msg, dest->ref); | ||
1614 | msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); | ||
1615 | if (importance <= TIPC_CRITICAL_IMPORTANCE) | ||
1616 | msg_set_importance(msg, importance); | ||
1617 | p_ptr->sent++; | ||
1618 | if (dest->node == tipc_own_addr) | ||
1619 | return port_recv_sections(p_ptr, num_sect, msg_sect); | ||
1620 | res = link_send_sections_fast(p_ptr, msg_sect, num_sect, dest->node); | ||
1621 | if (likely(res != -ELINKCONG)) | ||
1622 | return res; | ||
1623 | if (port_unreliable(p_ptr)) { | ||
1624 | /* Just calculate msg length and return */ | ||
1625 | return msg_calc_data_size(msg_sect, num_sect); | ||
1626 | } | ||
1627 | return -ELINKCONG; | ||
1628 | } | ||
1629 | |||
1630 | /** | ||
1631 | * tipc_send2port - send message sections to port identity | ||
1632 | */ | ||
1633 | |||
1634 | int tipc_send2port(u32 ref, | ||
1635 | struct tipc_portid const *dest, | ||
1636 | unsigned int num_sect, | ||
1637 | struct iovec const *msg_sect) | ||
1638 | { | ||
1639 | struct tipc_portid orig; | ||
1640 | |||
1641 | orig.ref = ref; | ||
1642 | orig.node = tipc_own_addr; | ||
1643 | return tipc_forward2port(ref, dest, num_sect, msg_sect, &orig, | ||
1644 | TIPC_PORT_IMPORTANCE); | ||
1645 | } | ||
1646 | |||
1647 | /** | ||
1648 | * tipc_forward_buf2port - forward message buffer to port identity | ||
1649 | */ | ||
1650 | int tipc_forward_buf2port(u32 ref, | ||
1651 | struct tipc_portid const *dest, | ||
1652 | struct sk_buff *buf, | ||
1653 | unsigned int dsz, | ||
1654 | struct tipc_portid const *orig, | ||
1655 | unsigned int importance) | ||
1656 | { | ||
1657 | struct port *p_ptr; | ||
1658 | struct tipc_msg *msg; | ||
1659 | int res; | ||
1660 | |||
1661 | p_ptr = (struct port *)ref_deref(ref); | ||
1662 | if (!p_ptr || p_ptr->publ.connected) | ||
1663 | return -EINVAL; | ||
1664 | |||
1665 | msg = &p_ptr->publ.phdr; | ||
1666 | msg_set_type(msg, TIPC_DIRECT_MSG); | ||
1667 | msg_set_orignode(msg, orig->node); | ||
1668 | msg_set_origport(msg, orig->ref); | ||
1669 | msg_set_destnode(msg, dest->node); | ||
1670 | msg_set_destport(msg, dest->ref); | ||
1671 | msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); | ||
1672 | if (importance <= TIPC_CRITICAL_IMPORTANCE) | ||
1673 | msg_set_importance(msg, importance); | ||
1674 | msg_set_size(msg, DIR_MSG_H_SIZE + dsz); | ||
1675 | if (skb_cow(buf, DIR_MSG_H_SIZE)) | ||
1676 | return -ENOMEM; | ||
1677 | |||
1678 | skb_push(buf, DIR_MSG_H_SIZE); | ||
1679 | memcpy(buf->data, (unchar *)msg, DIR_MSG_H_SIZE); | ||
1680 | msg_dbg(msg, "buf2port: "); | ||
1681 | p_ptr->sent++; | ||
1682 | if (dest->node == tipc_own_addr) | ||
1683 | return port_recv_msg(buf); | ||
1684 | res = tipc_send_buf_fast(buf, dest->node); | ||
1685 | if (likely(res != -ELINKCONG)) | ||
1686 | return res; | ||
1687 | if (port_unreliable(p_ptr)) | ||
1688 | return dsz; | ||
1689 | return -ELINKCONG; | ||
1690 | } | ||
1691 | |||
1692 | /** | ||
1693 | * tipc_send_buf2port - send message buffer to port identity | ||
1694 | */ | ||
1695 | |||
1696 | int tipc_send_buf2port(u32 ref, | ||
1697 | struct tipc_portid const *dest, | ||
1698 | struct sk_buff *buf, | ||
1699 | unsigned int dsz) | ||
1700 | { | ||
1701 | struct tipc_portid orig; | ||
1702 | |||
1703 | orig.ref = ref; | ||
1704 | orig.node = tipc_own_addr; | ||
1705 | return tipc_forward_buf2port(ref, dest, buf, dsz, &orig, | ||
1706 | TIPC_PORT_IMPORTANCE); | ||
1707 | } | ||
1708 | |||
diff --git a/net/tipc/port.h b/net/tipc/port.h new file mode 100644 index 000000000000..e829a99d3b7f --- /dev/null +++ b/net/tipc/port.h | |||
@@ -0,0 +1,209 @@ | |||
1 | /* | ||
2 | * net/tipc/port.h: Include file for TIPC port code | ||
3 | * | ||
4 | * Copyright (c) 1994-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_PORT_H | ||
38 | #define _TIPC_PORT_H | ||
39 | |||
40 | #include <net/tipc/tipc_port.h> | ||
41 | #include "ref.h" | ||
42 | #include "net.h" | ||
43 | #include "msg.h" | ||
44 | #include "dbg.h" | ||
45 | #include "node_subscr.h" | ||
46 | |||
47 | /** | ||
48 | * struct user_port - TIPC user port (used with native API) | ||
49 | * @user_ref: id of user who created user port | ||
50 | * @usr_handle: user-specified field | ||
51 | * @ref: object reference to associated TIPC port | ||
52 | * <various callback routines> | ||
53 | * @uport_list: adjacent user ports in list of ports held by user | ||
54 | */ | ||
55 | |||
56 | struct user_port { | ||
57 | u32 user_ref; | ||
58 | void *usr_handle; | ||
59 | u32 ref; | ||
60 | tipc_msg_err_event err_cb; | ||
61 | tipc_named_msg_err_event named_err_cb; | ||
62 | tipc_conn_shutdown_event conn_err_cb; | ||
63 | tipc_msg_event msg_cb; | ||
64 | tipc_named_msg_event named_msg_cb; | ||
65 | tipc_conn_msg_event conn_msg_cb; | ||
66 | tipc_continue_event continue_event_cb; | ||
67 | struct list_head uport_list; | ||
68 | }; | ||
69 | |||
70 | /** | ||
71 | * struct port - TIPC port structure | ||
72 | * @publ: TIPC port info available to privileged users | ||
73 | * @port_list: adjacent ports in TIPC's global list of ports | ||
74 | * @dispatcher: ptr to routine which handles received messages | ||
75 | * @wakeup: ptr to routine to call when port is no longer congested | ||
76 | * @user_port: ptr to user port associated with port (if any) | ||
77 | * @wait_list: adjacent ports in list of ports waiting on link congestion | ||
78 | * @congested_link: ptr to congested link port is waiting on | ||
79 | * @waiting_pkts: | ||
80 | * @sent: | ||
81 | * @acked: | ||
82 | * @publications: list of publications for port | ||
83 | * @pub_count: total # of publications port has made during its lifetime | ||
84 | * @max_pkt: maximum packet size "hint" used when building messages sent by port | ||
85 | * @probing_state: | ||
86 | * @probing_interval: | ||
87 | * @last_in_seqno: | ||
88 | * @timer_ref: | ||
89 | * @subscription: "node down" subscription used to terminate failed connections | ||
90 | */ | ||
91 | |||
92 | struct port { | ||
93 | struct tipc_port publ; | ||
94 | struct list_head port_list; | ||
95 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *); | ||
96 | void (*wakeup)(struct tipc_port *); | ||
97 | struct user_port *user_port; | ||
98 | struct list_head wait_list; | ||
99 | struct link *congested_link; | ||
100 | u32 waiting_pkts; | ||
101 | u32 sent; | ||
102 | u32 acked; | ||
103 | struct list_head publications; | ||
104 | u32 pub_count; | ||
105 | u32 max_pkt; | ||
106 | u32 probing_state; | ||
107 | u32 probing_interval; | ||
108 | u32 last_in_seqno; | ||
109 | struct timer_list timer; | ||
110 | struct node_subscr subscription; | ||
111 | }; | ||
112 | |||
113 | extern spinlock_t port_list_lock; | ||
114 | struct port_list; | ||
115 | |||
116 | int port_recv_sections(struct port *p_ptr, u32 num_sect, | ||
117 | struct iovec const *msg_sect); | ||
118 | int port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, | ||
119 | struct iovec const *msg_sect, u32 num_sect, | ||
120 | int err); | ||
121 | struct sk_buff *port_get_ports(void); | ||
122 | struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space); | ||
123 | void port_recv_proto_msg(struct sk_buff *buf); | ||
124 | void port_recv_mcast(struct sk_buff *buf, struct port_list *dp); | ||
125 | void port_reinit(void); | ||
126 | |||
127 | /** | ||
128 | * port_lock - lock port instance referred to and return its pointer | ||
129 | */ | ||
130 | |||
131 | static inline struct port *port_lock(u32 ref) | ||
132 | { | ||
133 | return (struct port *)ref_lock(ref); | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * port_unlock - unlock a port instance | ||
138 | * | ||
139 | * Can use pointer instead of ref_unlock() since port is already locked. | ||
140 | */ | ||
141 | |||
142 | static inline void port_unlock(struct port *p_ptr) | ||
143 | { | ||
144 | spin_unlock_bh(p_ptr->publ.lock); | ||
145 | } | ||
146 | |||
147 | static inline struct port* port_deref(u32 ref) | ||
148 | { | ||
149 | return (struct port *)ref_deref(ref); | ||
150 | } | ||
151 | |||
152 | static inline u32 peer_port(struct port *p_ptr) | ||
153 | { | ||
154 | return msg_destport(&p_ptr->publ.phdr); | ||
155 | } | ||
156 | |||
157 | static inline u32 peer_node(struct port *p_ptr) | ||
158 | { | ||
159 | return msg_destnode(&p_ptr->publ.phdr); | ||
160 | } | ||
161 | |||
162 | static inline int port_congested(struct port *p_ptr) | ||
163 | { | ||
164 | return((p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2)); | ||
165 | } | ||
166 | |||
167 | /** | ||
168 | * port_recv_msg - receive message from lower layer and deliver to port user | ||
169 | */ | ||
170 | |||
171 | static inline int port_recv_msg(struct sk_buff *buf) | ||
172 | { | ||
173 | struct port *p_ptr; | ||
174 | struct tipc_msg *msg = buf_msg(buf); | ||
175 | u32 destport = msg_destport(msg); | ||
176 | u32 dsz = msg_data_sz(msg); | ||
177 | u32 err; | ||
178 | |||
179 | /* forward unresolved named message */ | ||
180 | if (unlikely(!destport)) { | ||
181 | net_route_msg(buf); | ||
182 | return dsz; | ||
183 | } | ||
184 | |||
185 | /* validate destination & pass to port, otherwise reject message */ | ||
186 | p_ptr = port_lock(destport); | ||
187 | if (likely(p_ptr)) { | ||
188 | if (likely(p_ptr->publ.connected)) { | ||
189 | if ((unlikely(msg_origport(msg) != peer_port(p_ptr))) || | ||
190 | (unlikely(msg_orignode(msg) != peer_node(p_ptr))) || | ||
191 | (unlikely(!msg_connected(msg)))) { | ||
192 | err = TIPC_ERR_NO_PORT; | ||
193 | port_unlock(p_ptr); | ||
194 | goto reject; | ||
195 | } | ||
196 | } | ||
197 | err = p_ptr->dispatcher(&p_ptr->publ, buf); | ||
198 | port_unlock(p_ptr); | ||
199 | if (likely(!err)) | ||
200 | return dsz; | ||
201 | } else { | ||
202 | err = TIPC_ERR_NO_PORT; | ||
203 | } | ||
204 | reject: | ||
205 | dbg("port->rejecting, err = %x..\n",err); | ||
206 | return tipc_reject_msg(buf, err); | ||
207 | } | ||
208 | |||
209 | #endif | ||
diff --git a/net/tipc/ref.c b/net/tipc/ref.c new file mode 100644 index 000000000000..944093fe246f --- /dev/null +++ b/net/tipc/ref.c | |||
@@ -0,0 +1,189 @@ | |||
1 | /* | ||
2 | * net/tipc/ref.c: TIPC object registry code | ||
3 | * | ||
4 | * Copyright (c) 1991-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "ref.h" | ||
39 | #include "port.h" | ||
40 | #include "subscr.h" | ||
41 | #include "name_distr.h" | ||
42 | #include "name_table.h" | ||
43 | #include "config.h" | ||
44 | #include "discover.h" | ||
45 | #include "bearer.h" | ||
46 | #include "node.h" | ||
47 | #include "bcast.h" | ||
48 | |||
49 | /* | ||
50 | * Object reference table consists of 2**N entries. | ||
51 | * | ||
52 | * A used entry has object ptr != 0, reference == XXXX|own index | ||
53 | * (XXXX changes each time entry is acquired) | ||
54 | * A free entry has object ptr == 0, reference == YYYY|next free index | ||
55 | * (YYYY is one more than last used XXXX) | ||
56 | * | ||
57 | * Free list is initially chained from entry (2**N)-1 to entry 1. | ||
58 | * Entry 0 is not used to allow index 0 to indicate the end of the free list. | ||
59 | * | ||
60 | * Note: Any accidental reference of the form XXXX|0--0 won't match entry 0 | ||
61 | * because entry 0's reference field has the form XXXX|1--1. | ||
62 | */ | ||
63 | |||
64 | struct ref_table ref_table = { 0 }; | ||
65 | |||
66 | rwlock_t reftbl_lock = RW_LOCK_UNLOCKED; | ||
67 | |||
68 | /** | ||
69 | * ref_table_init - create reference table for objects | ||
70 | */ | ||
71 | |||
72 | int ref_table_init(u32 requested_size, u32 start) | ||
73 | { | ||
74 | struct reference *table; | ||
75 | u32 sz = 1 << 4; | ||
76 | u32 index_mask; | ||
77 | int i; | ||
78 | |||
79 | while (sz < requested_size) { | ||
80 | sz <<= 1; | ||
81 | } | ||
82 | table = (struct reference *)vmalloc(sz * sizeof(struct reference)); | ||
83 | if (table == NULL) | ||
84 | return -ENOMEM; | ||
85 | |||
86 | write_lock_bh(&reftbl_lock); | ||
87 | index_mask = sz - 1; | ||
88 | for (i = sz - 1; i >= 0; i--) { | ||
89 | table[i].object = 0; | ||
90 | table[i].lock = SPIN_LOCK_UNLOCKED; | ||
91 | table[i].data.next_plus_upper = (start & ~index_mask) + i - 1; | ||
92 | } | ||
93 | ref_table.entries = table; | ||
94 | ref_table.index_mask = index_mask; | ||
95 | ref_table.first_free = sz - 1; | ||
96 | ref_table.last_free = 1; | ||
97 | write_unlock_bh(&reftbl_lock); | ||
98 | return TIPC_OK; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * ref_table_stop - destroy reference table for objects | ||
103 | */ | ||
104 | |||
105 | void ref_table_stop(void) | ||
106 | { | ||
107 | if (!ref_table.entries) | ||
108 | return; | ||
109 | |||
110 | vfree(ref_table.entries); | ||
111 | ref_table.entries = 0; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * ref_acquire - create reference to an object | ||
116 | * | ||
117 | * Return a unique reference value which can be translated back to the pointer | ||
118 | * 'object' at a later time. Also, pass back a pointer to the lock protecting | ||
119 | * the object, but without locking it. | ||
120 | */ | ||
121 | |||
122 | u32 ref_acquire(void *object, spinlock_t **lock) | ||
123 | { | ||
124 | struct reference *entry; | ||
125 | u32 index; | ||
126 | u32 index_mask; | ||
127 | u32 next_plus_upper; | ||
128 | u32 reference = 0; | ||
129 | |||
130 | assert(ref_table.entries && object); | ||
131 | |||
132 | write_lock_bh(&reftbl_lock); | ||
133 | if (ref_table.first_free) { | ||
134 | index = ref_table.first_free; | ||
135 | entry = &(ref_table.entries[index]); | ||
136 | index_mask = ref_table.index_mask; | ||
137 | /* take lock in case a previous user of entry still holds it */ | ||
138 | spin_lock_bh(&entry->lock); | ||
139 | next_plus_upper = entry->data.next_plus_upper; | ||
140 | ref_table.first_free = next_plus_upper & index_mask; | ||
141 | reference = (next_plus_upper & ~index_mask) + index; | ||
142 | entry->data.reference = reference; | ||
143 | entry->object = object; | ||
144 | if (lock != 0) | ||
145 | *lock = &entry->lock; | ||
146 | spin_unlock_bh(&entry->lock); | ||
147 | } | ||
148 | write_unlock_bh(&reftbl_lock); | ||
149 | return reference; | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * ref_discard - invalidate references to an object | ||
154 | * | ||
155 | * Disallow future references to an object and free up the entry for re-use. | ||
156 | * Note: The entry's spin_lock may still be busy after discard | ||
157 | */ | ||
158 | |||
159 | void ref_discard(u32 ref) | ||
160 | { | ||
161 | struct reference *entry; | ||
162 | u32 index; | ||
163 | u32 index_mask; | ||
164 | |||
165 | assert(ref_table.entries); | ||
166 | assert(ref != 0); | ||
167 | |||
168 | write_lock_bh(&reftbl_lock); | ||
169 | index_mask = ref_table.index_mask; | ||
170 | index = ref & index_mask; | ||
171 | entry = &(ref_table.entries[index]); | ||
172 | assert(entry->object != 0); | ||
173 | assert(entry->data.reference == ref); | ||
174 | |||
175 | /* mark entry as unused */ | ||
176 | entry->object = 0; | ||
177 | if (ref_table.first_free == 0) | ||
178 | ref_table.first_free = index; | ||
179 | else | ||
180 | /* next_plus_upper is always XXXX|0--0 for last free entry */ | ||
181 | ref_table.entries[ref_table.last_free].data.next_plus_upper | ||
182 | |= index; | ||
183 | ref_table.last_free = index; | ||
184 | |||
185 | /* increment upper bits of entry to invalidate subsequent references */ | ||
186 | entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1); | ||
187 | write_unlock_bh(&reftbl_lock); | ||
188 | } | ||
189 | |||
diff --git a/net/tipc/ref.h b/net/tipc/ref.h new file mode 100644 index 000000000000..429cde57228a --- /dev/null +++ b/net/tipc/ref.h | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * net/tipc/ref.h: Include file for TIPC object registry code | ||
3 | * | ||
4 | * Copyright (c) 1991-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_REF_H | ||
38 | #define _TIPC_REF_H | ||
39 | |||
40 | /** | ||
41 | * struct reference - TIPC object reference entry | ||
42 | * @object: pointer to object associated with reference entry | ||
43 | * @lock: spinlock controlling access to object | ||
44 | * @data: reference value associated with object (or link to next unused entry) | ||
45 | */ | ||
46 | |||
47 | struct reference { | ||
48 | void *object; | ||
49 | spinlock_t lock; | ||
50 | union { | ||
51 | u32 next_plus_upper; | ||
52 | u32 reference; | ||
53 | } data; | ||
54 | }; | ||
55 | |||
56 | /** | ||
57 | * struct ref_table - table of TIPC object reference entries | ||
58 | * @entries: pointer to array of reference entries | ||
59 | * @index_mask: bitmask for array index portion of reference values | ||
60 | * @first_free: array index of first unused object reference entry | ||
61 | * @last_free: array index of last unused object reference entry | ||
62 | */ | ||
63 | |||
64 | struct ref_table { | ||
65 | struct reference *entries; | ||
66 | u32 index_mask; | ||
67 | u32 first_free; | ||
68 | u32 last_free; | ||
69 | }; | ||
70 | |||
71 | extern struct ref_table ref_table; | ||
72 | |||
73 | int ref_table_init(u32 requested_size, u32 start); | ||
74 | void ref_table_stop(void); | ||
75 | |||
76 | u32 ref_acquire(void *object, spinlock_t **lock); | ||
77 | void ref_discard(u32 ref); | ||
78 | |||
79 | |||
80 | /** | ||
81 | * ref_lock - lock referenced object and return pointer to it | ||
82 | */ | ||
83 | |||
84 | static inline void *ref_lock(u32 ref) | ||
85 | { | ||
86 | if (likely(ref_table.entries)) { | ||
87 | struct reference *r = | ||
88 | &ref_table.entries[ref & ref_table.index_mask]; | ||
89 | |||
90 | spin_lock_bh(&r->lock); | ||
91 | if (likely(r->data.reference == ref)) | ||
92 | return r->object; | ||
93 | spin_unlock_bh(&r->lock); | ||
94 | } | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * ref_unlock - unlock referenced object | ||
100 | */ | ||
101 | |||
102 | static inline void ref_unlock(u32 ref) | ||
103 | { | ||
104 | if (likely(ref_table.entries)) { | ||
105 | struct reference *r = | ||
106 | &ref_table.entries[ref & ref_table.index_mask]; | ||
107 | |||
108 | if (likely(r->data.reference == ref)) | ||
109 | spin_unlock_bh(&r->lock); | ||
110 | else | ||
111 | err("ref_unlock() invoked using obsolete reference\n"); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * ref_deref - return pointer referenced object (without locking it) | ||
117 | */ | ||
118 | |||
119 | static inline void *ref_deref(u32 ref) | ||
120 | { | ||
121 | if (likely(ref_table.entries)) { | ||
122 | struct reference *r = | ||
123 | &ref_table.entries[ref & ref_table.index_mask]; | ||
124 | |||
125 | if (likely(r->data.reference == ref)) | ||
126 | return r->object; | ||
127 | } | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | #endif | ||
diff --git a/net/tipc/socket.c b/net/tipc/socket.c new file mode 100644 index 000000000000..d21f8c0cd25a --- /dev/null +++ b/net/tipc/socket.c | |||
@@ -0,0 +1,1726 @@ | |||
1 | /* | ||
2 | * net/tipc/socket.c: TIPC socket API | ||
3 | * | ||
4 | * Copyright (c) 2001-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include <linux/module.h> | ||
38 | #include <linux/types.h> | ||
39 | #include <linux/net.h> | ||
40 | #include <linux/socket.h> | ||
41 | #include <linux/errno.h> | ||
42 | #include <linux/mm.h> | ||
43 | #include <linux/slab.h> | ||
44 | #include <linux/poll.h> | ||
45 | #include <linux/version.h> | ||
46 | #include <linux/fcntl.h> | ||
47 | #include <linux/version.h> | ||
48 | #include <asm/semaphore.h> | ||
49 | #include <asm/string.h> | ||
50 | #include <asm/atomic.h> | ||
51 | #include <net/sock.h> | ||
52 | |||
53 | #include <linux/tipc.h> | ||
54 | #include <linux/tipc_config.h> | ||
55 | #include <net/tipc/tipc_msg.h> | ||
56 | #include <net/tipc/tipc_port.h> | ||
57 | |||
58 | #include "core.h" | ||
59 | |||
60 | #define SS_LISTENING -1 /* socket is listening */ | ||
61 | #define SS_READY -2 /* socket is connectionless */ | ||
62 | |||
63 | #define OVERLOAD_LIMIT_BASE 5000 | ||
64 | |||
65 | struct tipc_sock { | ||
66 | struct sock sk; | ||
67 | struct tipc_port *p; | ||
68 | struct semaphore sem; | ||
69 | }; | ||
70 | |||
71 | #define tipc_sk(sk) ((struct tipc_sock*)sk) | ||
72 | |||
73 | static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); | ||
74 | static void wakeupdispatch(struct tipc_port *tport); | ||
75 | |||
76 | static struct proto_ops packet_ops; | ||
77 | static struct proto_ops stream_ops; | ||
78 | static struct proto_ops msg_ops; | ||
79 | |||
80 | static struct proto tipc_proto; | ||
81 | |||
82 | static int sockets_enabled = 0; | ||
83 | |||
84 | static atomic_t tipc_queue_size = ATOMIC_INIT(0); | ||
85 | |||
86 | |||
87 | /* | ||
88 | * sock_lock(): Lock a port/socket pair. lock_sock() can | ||
89 | * not be used here, since the same lock must protect ports | ||
90 | * with non-socket interfaces. | ||
91 | * See net.c for description of locking policy. | ||
92 | */ | ||
93 | static inline void sock_lock(struct tipc_sock* tsock) | ||
94 | { | ||
95 | spin_lock_bh(tsock->p->lock); | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * sock_unlock(): Unlock a port/socket pair | ||
100 | */ | ||
101 | static inline void sock_unlock(struct tipc_sock* tsock) | ||
102 | { | ||
103 | spin_unlock_bh(tsock->p->lock); | ||
104 | } | ||
105 | |||
106 | /** | ||
107 | * pollmask - determine the current set of poll() events for a socket | ||
108 | * @sock: socket structure | ||
109 | * | ||
110 | * TIPC sets the returned events as follows: | ||
111 | * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty | ||
112 | * or if a connection-oriented socket is does not have an active connection | ||
113 | * (i.e. a read operation will not block). | ||
114 | * b) POLLOUT is set except when a socket's connection has been terminated | ||
115 | * (i.e. a write operation will not block). | ||
116 | * c) POLLHUP is set when a socket's connection has been terminated. | ||
117 | * | ||
118 | * IMPORTANT: The fact that a read or write operation will not block does NOT | ||
119 | * imply that the operation will succeed! | ||
120 | * | ||
121 | * Returns pollmask value | ||
122 | */ | ||
123 | |||
124 | static inline u32 pollmask(struct socket *sock) | ||
125 | { | ||
126 | u32 mask; | ||
127 | |||
128 | if ((skb_queue_len(&sock->sk->sk_receive_queue) != 0) || | ||
129 | (sock->state == SS_UNCONNECTED) || | ||
130 | (sock->state == SS_DISCONNECTING)) | ||
131 | mask = (POLLRDNORM | POLLIN); | ||
132 | else | ||
133 | mask = 0; | ||
134 | |||
135 | if (sock->state == SS_DISCONNECTING) | ||
136 | mask |= POLLHUP; | ||
137 | else | ||
138 | mask |= POLLOUT; | ||
139 | |||
140 | return mask; | ||
141 | } | ||
142 | |||
143 | |||
144 | /** | ||
145 | * advance_queue - discard first buffer in queue | ||
146 | * @tsock: TIPC socket | ||
147 | */ | ||
148 | |||
149 | static inline void advance_queue(struct tipc_sock *tsock) | ||
150 | { | ||
151 | sock_lock(tsock); | ||
152 | buf_discard(skb_dequeue(&tsock->sk.sk_receive_queue)); | ||
153 | sock_unlock(tsock); | ||
154 | atomic_dec(&tipc_queue_size); | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * tipc_create - create a TIPC socket | ||
159 | * @sock: pre-allocated socket structure | ||
160 | * @protocol: protocol indicator (must be 0) | ||
161 | * | ||
162 | * This routine creates and attaches a 'struct sock' to the 'struct socket', | ||
163 | * then create and attaches a TIPC port to the 'struct sock' part. | ||
164 | * | ||
165 | * Returns 0 on success, errno otherwise | ||
166 | */ | ||
167 | static int tipc_create(struct socket *sock, int protocol) | ||
168 | { | ||
169 | struct tipc_sock *tsock; | ||
170 | struct tipc_port *port; | ||
171 | struct sock *sk; | ||
172 | u32 ref; | ||
173 | |||
174 | if ((sock->type != SOCK_STREAM) && | ||
175 | (sock->type != SOCK_SEQPACKET) && | ||
176 | (sock->type != SOCK_DGRAM) && | ||
177 | (sock->type != SOCK_RDM)) | ||
178 | return -EPROTOTYPE; | ||
179 | |||
180 | if (unlikely(protocol != 0)) | ||
181 | return -EPROTONOSUPPORT; | ||
182 | |||
183 | ref = tipc_createport_raw(0, &dispatch, &wakeupdispatch, TIPC_LOW_IMPORTANCE); | ||
184 | if (unlikely(!ref)) | ||
185 | return -ENOMEM; | ||
186 | |||
187 | sock->state = SS_UNCONNECTED; | ||
188 | |||
189 | switch (sock->type) { | ||
190 | case SOCK_STREAM: | ||
191 | sock->ops = &stream_ops; | ||
192 | break; | ||
193 | case SOCK_SEQPACKET: | ||
194 | sock->ops = &packet_ops; | ||
195 | break; | ||
196 | case SOCK_DGRAM: | ||
197 | tipc_set_portunreliable(ref, 1); | ||
198 | /* fall through */ | ||
199 | case SOCK_RDM: | ||
200 | tipc_set_portunreturnable(ref, 1); | ||
201 | sock->ops = &msg_ops; | ||
202 | sock->state = SS_READY; | ||
203 | break; | ||
204 | } | ||
205 | |||
206 | sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1); | ||
207 | if (!sk) { | ||
208 | tipc_deleteport(ref); | ||
209 | return -ENOMEM; | ||
210 | } | ||
211 | |||
212 | sock_init_data(sock, sk); | ||
213 | init_waitqueue_head(sk->sk_sleep); | ||
214 | sk->sk_rcvtimeo = 8 * HZ; /* default connect timeout = 8s */ | ||
215 | |||
216 | tsock = tipc_sk(sk); | ||
217 | port = tipc_get_port(ref); | ||
218 | |||
219 | tsock->p = port; | ||
220 | port->usr_handle = tsock; | ||
221 | |||
222 | init_MUTEX(&tsock->sem); | ||
223 | |||
224 | dbg("sock_create: %x\n",tsock); | ||
225 | |||
226 | atomic_inc(&tipc_user_count); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | /** | ||
232 | * release - destroy a TIPC socket | ||
233 | * @sock: socket to destroy | ||
234 | * | ||
235 | * This routine cleans up any messages that are still queued on the socket. | ||
236 | * For DGRAM and RDM socket types, all queued messages are rejected. | ||
237 | * For SEQPACKET and STREAM socket types, the first message is rejected | ||
238 | * and any others are discarded. (If the first message on a STREAM socket | ||
239 | * is partially-read, it is discarded and the next one is rejected instead.) | ||
240 | * | ||
241 | * NOTE: Rejected messages are not necessarily returned to the sender! They | ||
242 | * are returned or discarded according to the "destination droppable" setting | ||
243 | * specified for the message by the sender. | ||
244 | * | ||
245 | * Returns 0 on success, errno otherwise | ||
246 | */ | ||
247 | |||
248 | static int release(struct socket *sock) | ||
249 | { | ||
250 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
251 | struct sock *sk = sock->sk; | ||
252 | int res = TIPC_OK; | ||
253 | struct sk_buff *buf; | ||
254 | |||
255 | dbg("sock_delete: %x\n",tsock); | ||
256 | if (!tsock) | ||
257 | return 0; | ||
258 | down_interruptible(&tsock->sem); | ||
259 | if (!sock->sk) { | ||
260 | up(&tsock->sem); | ||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | /* Reject unreceived messages, unless no longer connected */ | ||
265 | |||
266 | while (sock->state != SS_DISCONNECTING) { | ||
267 | sock_lock(tsock); | ||
268 | buf = skb_dequeue(&sk->sk_receive_queue); | ||
269 | if (!buf) | ||
270 | tsock->p->usr_handle = 0; | ||
271 | sock_unlock(tsock); | ||
272 | if (!buf) | ||
273 | break; | ||
274 | if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) | ||
275 | buf_discard(buf); | ||
276 | else | ||
277 | tipc_reject_msg(buf, TIPC_ERR_NO_PORT); | ||
278 | atomic_dec(&tipc_queue_size); | ||
279 | } | ||
280 | |||
281 | /* Delete TIPC port */ | ||
282 | |||
283 | res = tipc_deleteport(tsock->p->ref); | ||
284 | sock->sk = NULL; | ||
285 | |||
286 | /* Discard any remaining messages */ | ||
287 | |||
288 | while ((buf = skb_dequeue(&sk->sk_receive_queue))) { | ||
289 | buf_discard(buf); | ||
290 | atomic_dec(&tipc_queue_size); | ||
291 | } | ||
292 | |||
293 | up(&tsock->sem); | ||
294 | |||
295 | sock_put(sk); | ||
296 | |||
297 | atomic_dec(&tipc_user_count); | ||
298 | return res; | ||
299 | } | ||
300 | |||
301 | /** | ||
302 | * bind - associate or disassocate TIPC name(s) with a socket | ||
303 | * @sock: socket structure | ||
304 | * @uaddr: socket address describing name(s) and desired operation | ||
305 | * @uaddr_len: size of socket address data structure | ||
306 | * | ||
307 | * Name and name sequence binding is indicated using a positive scope value; | ||
308 | * a negative scope value unbinds the specified name. Specifying no name | ||
309 | * (i.e. a socket address length of 0) unbinds all names from the socket. | ||
310 | * | ||
311 | * Returns 0 on success, errno otherwise | ||
312 | */ | ||
313 | |||
314 | static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) | ||
315 | { | ||
316 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
317 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; | ||
318 | int res; | ||
319 | |||
320 | if (down_interruptible(&tsock->sem)) | ||
321 | return -ERESTARTSYS; | ||
322 | |||
323 | if (unlikely(!uaddr_len)) { | ||
324 | res = tipc_withdraw(tsock->p->ref, 0, 0); | ||
325 | goto exit; | ||
326 | } | ||
327 | |||
328 | if (uaddr_len < sizeof(struct sockaddr_tipc)) { | ||
329 | res = -EINVAL; | ||
330 | goto exit; | ||
331 | } | ||
332 | |||
333 | if (addr->family != AF_TIPC) { | ||
334 | res = -EAFNOSUPPORT; | ||
335 | goto exit; | ||
336 | } | ||
337 | if (addr->addrtype == TIPC_ADDR_NAME) | ||
338 | addr->addr.nameseq.upper = addr->addr.nameseq.lower; | ||
339 | else if (addr->addrtype != TIPC_ADDR_NAMESEQ) { | ||
340 | res = -EAFNOSUPPORT; | ||
341 | goto exit; | ||
342 | } | ||
343 | |||
344 | if (addr->scope > 0) | ||
345 | res = tipc_publish(tsock->p->ref, addr->scope, | ||
346 | &addr->addr.nameseq); | ||
347 | else | ||
348 | res = tipc_withdraw(tsock->p->ref, -addr->scope, | ||
349 | &addr->addr.nameseq); | ||
350 | exit: | ||
351 | up(&tsock->sem); | ||
352 | return res; | ||
353 | } | ||
354 | |||
355 | /** | ||
356 | * get_name - get port ID of socket or peer socket | ||
357 | * @sock: socket structure | ||
358 | * @uaddr: area for returned socket address | ||
359 | * @uaddr_len: area for returned length of socket address | ||
360 | * @peer: 0 to obtain socket name, 1 to obtain peer socket name | ||
361 | * | ||
362 | * Returns 0 on success, errno otherwise | ||
363 | */ | ||
364 | |||
365 | static int get_name(struct socket *sock, struct sockaddr *uaddr, | ||
366 | int *uaddr_len, int peer) | ||
367 | { | ||
368 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
369 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; | ||
370 | u32 res; | ||
371 | |||
372 | if (down_interruptible(&tsock->sem)) | ||
373 | return -ERESTARTSYS; | ||
374 | |||
375 | *uaddr_len = sizeof(*addr); | ||
376 | addr->addrtype = TIPC_ADDR_ID; | ||
377 | addr->family = AF_TIPC; | ||
378 | addr->scope = 0; | ||
379 | if (peer) | ||
380 | res = tipc_peer(tsock->p->ref, &addr->addr.id); | ||
381 | else | ||
382 | res = tipc_ownidentity(tsock->p->ref, &addr->addr.id); | ||
383 | addr->addr.name.domain = 0; | ||
384 | |||
385 | up(&tsock->sem); | ||
386 | return res; | ||
387 | } | ||
388 | |||
389 | /** | ||
390 | * poll - read and possibly block on pollmask | ||
391 | * @file: file structure associated with the socket | ||
392 | * @sock: socket for which to calculate the poll bits | ||
393 | * @wait: ??? | ||
394 | * | ||
395 | * Returns the pollmask | ||
396 | */ | ||
397 | |||
398 | static unsigned int poll(struct file *file, struct socket *sock, | ||
399 | poll_table *wait) | ||
400 | { | ||
401 | poll_wait(file, sock->sk->sk_sleep, wait); | ||
402 | /* NEED LOCK HERE? */ | ||
403 | return pollmask(sock); | ||
404 | } | ||
405 | |||
406 | /** | ||
407 | * dest_name_check - verify user is permitted to send to specified port name | ||
408 | * @dest: destination address | ||
409 | * @m: descriptor for message to be sent | ||
410 | * | ||
411 | * Prevents restricted configuration commands from being issued by | ||
412 | * unauthorized users. | ||
413 | * | ||
414 | * Returns 0 if permission is granted, otherwise errno | ||
415 | */ | ||
416 | |||
417 | static inline int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) | ||
418 | { | ||
419 | struct tipc_cfg_msg_hdr hdr; | ||
420 | |||
421 | if (likely(dest->addr.name.name.type >= TIPC_RESERVED_TYPES)) | ||
422 | return 0; | ||
423 | if (likely(dest->addr.name.name.type == TIPC_TOP_SRV)) | ||
424 | return 0; | ||
425 | |||
426 | if (likely(dest->addr.name.name.type != TIPC_CFG_SRV)) | ||
427 | return -EACCES; | ||
428 | |||
429 | if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr))) | ||
430 | return -EFAULT; | ||
431 | if ((ntohs(hdr.tcm_type) & 0xC000) & (!capable(CAP_NET_ADMIN))) | ||
432 | return -EACCES; | ||
433 | |||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | /** | ||
438 | * send_msg - send message in connectionless manner | ||
439 | * @iocb: (unused) | ||
440 | * @sock: socket structure | ||
441 | * @m: message to send | ||
442 | * @total_len: (unused) | ||
443 | * | ||
444 | * Message must have an destination specified explicitly. | ||
445 | * Used for SOCK_RDM and SOCK_DGRAM messages, | ||
446 | * and for 'SYN' messages on SOCK_SEQPACKET and SOCK_STREAM connections. | ||
447 | * (Note: 'SYN+' is prohibited on SOCK_STREAM.) | ||
448 | * | ||
449 | * Returns the number of bytes sent on success, or errno otherwise | ||
450 | */ | ||
451 | |||
452 | static int send_msg(struct kiocb *iocb, struct socket *sock, | ||
453 | struct msghdr *m, size_t total_len) | ||
454 | { | ||
455 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
456 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; | ||
457 | struct sk_buff *buf; | ||
458 | int needs_conn; | ||
459 | int res = -EINVAL; | ||
460 | |||
461 | if (unlikely(!dest)) | ||
462 | return -EDESTADDRREQ; | ||
463 | if (unlikely(dest->family != AF_TIPC)) | ||
464 | return -EINVAL; | ||
465 | |||
466 | needs_conn = (sock->state != SS_READY); | ||
467 | if (unlikely(needs_conn)) { | ||
468 | if (sock->state == SS_LISTENING) | ||
469 | return -EPIPE; | ||
470 | if (sock->state != SS_UNCONNECTED) | ||
471 | return -EISCONN; | ||
472 | if ((tsock->p->published) || | ||
473 | ((sock->type == SOCK_STREAM) && (total_len != 0))) | ||
474 | return -EOPNOTSUPP; | ||
475 | } | ||
476 | |||
477 | if (down_interruptible(&tsock->sem)) | ||
478 | return -ERESTARTSYS; | ||
479 | |||
480 | if (needs_conn) { | ||
481 | |||
482 | /* Abort any pending connection attempts (very unlikely) */ | ||
483 | |||
484 | while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) { | ||
485 | tipc_reject_msg(buf, TIPC_ERR_NO_PORT); | ||
486 | atomic_dec(&tipc_queue_size); | ||
487 | } | ||
488 | |||
489 | sock->state = SS_CONNECTING; | ||
490 | } | ||
491 | |||
492 | do { | ||
493 | if (dest->addrtype == TIPC_ADDR_NAME) { | ||
494 | if ((res = dest_name_check(dest, m))) | ||
495 | goto exit; | ||
496 | res = tipc_send2name(tsock->p->ref, | ||
497 | &dest->addr.name.name, | ||
498 | dest->addr.name.domain, | ||
499 | m->msg_iovlen, | ||
500 | m->msg_iov); | ||
501 | } | ||
502 | else if (dest->addrtype == TIPC_ADDR_ID) { | ||
503 | res = tipc_send2port(tsock->p->ref, | ||
504 | &dest->addr.id, | ||
505 | m->msg_iovlen, | ||
506 | m->msg_iov); | ||
507 | } | ||
508 | else if (dest->addrtype == TIPC_ADDR_MCAST) { | ||
509 | if (needs_conn) { | ||
510 | res = -EOPNOTSUPP; | ||
511 | goto exit; | ||
512 | } | ||
513 | if ((res = dest_name_check(dest, m))) | ||
514 | goto exit; | ||
515 | res = tipc_multicast(tsock->p->ref, | ||
516 | &dest->addr.nameseq, | ||
517 | 0, | ||
518 | m->msg_iovlen, | ||
519 | m->msg_iov); | ||
520 | } | ||
521 | if (likely(res != -ELINKCONG)) { | ||
522 | exit: | ||
523 | up(&tsock->sem); | ||
524 | return res; | ||
525 | } | ||
526 | if (m->msg_flags & MSG_DONTWAIT) { | ||
527 | res = -EWOULDBLOCK; | ||
528 | goto exit; | ||
529 | } | ||
530 | if (wait_event_interruptible(*sock->sk->sk_sleep, | ||
531 | !tsock->p->congested)) { | ||
532 | res = -ERESTARTSYS; | ||
533 | goto exit; | ||
534 | } | ||
535 | } while (1); | ||
536 | } | ||
537 | |||
538 | /** | ||
539 | * send_packet - send a connection-oriented message | ||
540 | * @iocb: (unused) | ||
541 | * @sock: socket structure | ||
542 | * @m: message to send | ||
543 | * @total_len: (unused) | ||
544 | * | ||
545 | * Used for SOCK_SEQPACKET messages and SOCK_STREAM data. | ||
546 | * | ||
547 | * Returns the number of bytes sent on success, or errno otherwise | ||
548 | */ | ||
549 | |||
550 | static int send_packet(struct kiocb *iocb, struct socket *sock, | ||
551 | struct msghdr *m, size_t total_len) | ||
552 | { | ||
553 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
554 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; | ||
555 | int res; | ||
556 | |||
557 | /* Handle implied connection establishment */ | ||
558 | |||
559 | if (unlikely(dest)) | ||
560 | return send_msg(iocb, sock, m, total_len); | ||
561 | |||
562 | if (down_interruptible(&tsock->sem)) { | ||
563 | return -ERESTARTSYS; | ||
564 | } | ||
565 | |||
566 | if (unlikely(sock->state != SS_CONNECTED)) { | ||
567 | if (sock->state == SS_DISCONNECTING) | ||
568 | res = -EPIPE; | ||
569 | else | ||
570 | res = -ENOTCONN; | ||
571 | goto exit; | ||
572 | } | ||
573 | |||
574 | do { | ||
575 | res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov); | ||
576 | if (likely(res != -ELINKCONG)) { | ||
577 | exit: | ||
578 | up(&tsock->sem); | ||
579 | return res; | ||
580 | } | ||
581 | if (m->msg_flags & MSG_DONTWAIT) { | ||
582 | res = -EWOULDBLOCK; | ||
583 | goto exit; | ||
584 | } | ||
585 | if (wait_event_interruptible(*sock->sk->sk_sleep, | ||
586 | !tsock->p->congested)) { | ||
587 | res = -ERESTARTSYS; | ||
588 | goto exit; | ||
589 | } | ||
590 | } while (1); | ||
591 | } | ||
592 | |||
593 | /** | ||
594 | * send_stream - send stream-oriented data | ||
595 | * @iocb: (unused) | ||
596 | * @sock: socket structure | ||
597 | * @m: data to send | ||
598 | * @total_len: total length of data to be sent | ||
599 | * | ||
600 | * Used for SOCK_STREAM data. | ||
601 | * | ||
602 | * Returns the number of bytes sent on success, or errno otherwise | ||
603 | */ | ||
604 | |||
605 | |||
606 | static int send_stream(struct kiocb *iocb, struct socket *sock, | ||
607 | struct msghdr *m, size_t total_len) | ||
608 | { | ||
609 | struct msghdr my_msg; | ||
610 | struct iovec my_iov; | ||
611 | struct iovec *curr_iov; | ||
612 | int curr_iovlen; | ||
613 | char __user *curr_start; | ||
614 | int curr_left; | ||
615 | int bytes_to_send; | ||
616 | int res; | ||
617 | |||
618 | if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE)) | ||
619 | return send_packet(iocb, sock, m, total_len); | ||
620 | |||
621 | /* Can only send large data streams if already connected */ | ||
622 | |||
623 | if (unlikely(sock->state != SS_CONNECTED)) { | ||
624 | if (sock->state == SS_DISCONNECTING) | ||
625 | return -EPIPE; | ||
626 | else | ||
627 | return -ENOTCONN; | ||
628 | } | ||
629 | |||
630 | /* | ||
631 | * Send each iovec entry using one or more messages | ||
632 | * | ||
633 | * Note: This algorithm is good for the most likely case | ||
634 | * (i.e. one large iovec entry), but could be improved to pass sets | ||
635 | * of small iovec entries into send_packet(). | ||
636 | */ | ||
637 | |||
638 | my_msg = *m; | ||
639 | curr_iov = my_msg.msg_iov; | ||
640 | curr_iovlen = my_msg.msg_iovlen; | ||
641 | my_msg.msg_iov = &my_iov; | ||
642 | my_msg.msg_iovlen = 1; | ||
643 | |||
644 | while (curr_iovlen--) { | ||
645 | curr_start = curr_iov->iov_base; | ||
646 | curr_left = curr_iov->iov_len; | ||
647 | |||
648 | while (curr_left) { | ||
649 | bytes_to_send = (curr_left < TIPC_MAX_USER_MSG_SIZE) | ||
650 | ? curr_left : TIPC_MAX_USER_MSG_SIZE; | ||
651 | my_iov.iov_base = curr_start; | ||
652 | my_iov.iov_len = bytes_to_send; | ||
653 | if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) | ||
654 | return res; | ||
655 | curr_left -= bytes_to_send; | ||
656 | curr_start += bytes_to_send; | ||
657 | } | ||
658 | |||
659 | curr_iov++; | ||
660 | } | ||
661 | |||
662 | return total_len; | ||
663 | } | ||
664 | |||
665 | /** | ||
666 | * auto_connect - complete connection setup to a remote port | ||
667 | * @sock: socket structure | ||
668 | * @tsock: TIPC-specific socket structure | ||
669 | * @msg: peer's response message | ||
670 | * | ||
671 | * Returns 0 on success, errno otherwise | ||
672 | */ | ||
673 | |||
674 | static int auto_connect(struct socket *sock, struct tipc_sock *tsock, | ||
675 | struct tipc_msg *msg) | ||
676 | { | ||
677 | struct tipc_portid peer; | ||
678 | |||
679 | if (msg_errcode(msg)) { | ||
680 | sock->state = SS_DISCONNECTING; | ||
681 | return -ECONNREFUSED; | ||
682 | } | ||
683 | |||
684 | peer.ref = msg_origport(msg); | ||
685 | peer.node = msg_orignode(msg); | ||
686 | tipc_connect2port(tsock->p->ref, &peer); | ||
687 | tipc_set_portimportance(tsock->p->ref, msg_importance(msg)); | ||
688 | sock->state = SS_CONNECTED; | ||
689 | return 0; | ||
690 | } | ||
691 | |||
692 | /** | ||
693 | * set_orig_addr - capture sender's address for received message | ||
694 | * @m: descriptor for message info | ||
695 | * @msg: received message header | ||
696 | * | ||
697 | * Note: Address is not captured if not requested by receiver. | ||
698 | */ | ||
699 | |||
700 | static inline void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) | ||
701 | { | ||
702 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)m->msg_name; | ||
703 | |||
704 | if (addr) { | ||
705 | addr->family = AF_TIPC; | ||
706 | addr->addrtype = TIPC_ADDR_ID; | ||
707 | addr->addr.id.ref = msg_origport(msg); | ||
708 | addr->addr.id.node = msg_orignode(msg); | ||
709 | addr->addr.name.domain = 0; /* could leave uninitialized */ | ||
710 | addr->scope = 0; /* could leave uninitialized */ | ||
711 | m->msg_namelen = sizeof(struct sockaddr_tipc); | ||
712 | } | ||
713 | } | ||
714 | |||
715 | /** | ||
716 | * anc_data_recv - optionally capture ancillary data for received message | ||
717 | * @m: descriptor for message info | ||
718 | * @msg: received message header | ||
719 | * @tport: TIPC port associated with message | ||
720 | * | ||
721 | * Note: Ancillary data is not captured if not requested by receiver. | ||
722 | * | ||
723 | * Returns 0 if successful, otherwise errno | ||
724 | */ | ||
725 | |||
726 | static inline int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | ||
727 | struct tipc_port *tport) | ||
728 | { | ||
729 | u32 anc_data[3]; | ||
730 | u32 err; | ||
731 | u32 dest_type; | ||
732 | int res; | ||
733 | |||
734 | if (likely(m->msg_controllen == 0)) | ||
735 | return 0; | ||
736 | |||
737 | /* Optionally capture errored message object(s) */ | ||
738 | |||
739 | err = msg ? msg_errcode(msg) : 0; | ||
740 | if (unlikely(err)) { | ||
741 | anc_data[0] = err; | ||
742 | anc_data[1] = msg_data_sz(msg); | ||
743 | if ((res = put_cmsg(m, SOL_SOCKET, TIPC_ERRINFO, 8, anc_data))) | ||
744 | return res; | ||
745 | if (anc_data[1] && | ||
746 | (res = put_cmsg(m, SOL_SOCKET, TIPC_RETDATA, anc_data[1], | ||
747 | msg_data(msg)))) | ||
748 | return res; | ||
749 | } | ||
750 | |||
751 | /* Optionally capture message destination object */ | ||
752 | |||
753 | dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG; | ||
754 | switch (dest_type) { | ||
755 | case TIPC_NAMED_MSG: | ||
756 | anc_data[0] = msg_nametype(msg); | ||
757 | anc_data[1] = msg_namelower(msg); | ||
758 | anc_data[2] = msg_namelower(msg); | ||
759 | break; | ||
760 | case TIPC_MCAST_MSG: | ||
761 | anc_data[0] = msg_nametype(msg); | ||
762 | anc_data[1] = msg_namelower(msg); | ||
763 | anc_data[2] = msg_nameupper(msg); | ||
764 | break; | ||
765 | case TIPC_CONN_MSG: | ||
766 | anc_data[0] = tport->conn_type; | ||
767 | anc_data[1] = tport->conn_instance; | ||
768 | anc_data[2] = tport->conn_instance; | ||
769 | break; | ||
770 | default: | ||
771 | anc_data[0] = 0; | ||
772 | } | ||
773 | if (anc_data[0] && | ||
774 | (res = put_cmsg(m, SOL_SOCKET, TIPC_DESTNAME, 12, anc_data))) | ||
775 | return res; | ||
776 | |||
777 | return 0; | ||
778 | } | ||
779 | |||
780 | /** | ||
781 | * recv_msg - receive packet-oriented message | ||
782 | * @iocb: (unused) | ||
783 | * @m: descriptor for message info | ||
784 | * @buf_len: total size of user buffer area | ||
785 | * @flags: receive flags | ||
786 | * | ||
787 | * Used for SOCK_DGRAM, SOCK_RDM, and SOCK_SEQPACKET messages. | ||
788 | * If the complete message doesn't fit in user area, truncate it. | ||
789 | * | ||
790 | * Returns size of returned message data, errno otherwise | ||
791 | */ | ||
792 | |||
793 | static int recv_msg(struct kiocb *iocb, struct socket *sock, | ||
794 | struct msghdr *m, size_t buf_len, int flags) | ||
795 | { | ||
796 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
797 | struct sk_buff *buf; | ||
798 | struct tipc_msg *msg; | ||
799 | unsigned int q_len; | ||
800 | unsigned int sz; | ||
801 | u32 err; | ||
802 | int res; | ||
803 | |||
804 | /* Currently doesn't support receiving into multiple iovec entries */ | ||
805 | |||
806 | if (m->msg_iovlen != 1) | ||
807 | return -EOPNOTSUPP; | ||
808 | |||
809 | /* Catch invalid receive attempts */ | ||
810 | |||
811 | if (unlikely(!buf_len)) | ||
812 | return -EINVAL; | ||
813 | |||
814 | if (sock->type == SOCK_SEQPACKET) { | ||
815 | if (unlikely(sock->state == SS_UNCONNECTED)) | ||
816 | return -ENOTCONN; | ||
817 | if (unlikely((sock->state == SS_DISCONNECTING) && | ||
818 | (skb_queue_len(&sock->sk->sk_receive_queue) == 0))) | ||
819 | return -ENOTCONN; | ||
820 | } | ||
821 | |||
822 | /* Look for a message in receive queue; wait if necessary */ | ||
823 | |||
824 | if (unlikely(down_interruptible(&tsock->sem))) | ||
825 | return -ERESTARTSYS; | ||
826 | |||
827 | restart: | ||
828 | if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && | ||
829 | (flags & MSG_DONTWAIT))) { | ||
830 | res = -EWOULDBLOCK; | ||
831 | goto exit; | ||
832 | } | ||
833 | |||
834 | if ((res = wait_event_interruptible( | ||
835 | *sock->sk->sk_sleep, | ||
836 | ((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) || | ||
837 | (sock->state == SS_DISCONNECTING))) )) { | ||
838 | goto exit; | ||
839 | } | ||
840 | |||
841 | /* Catch attempt to receive on an already terminated connection */ | ||
842 | /* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */ | ||
843 | |||
844 | if (!q_len) { | ||
845 | res = -ENOTCONN; | ||
846 | goto exit; | ||
847 | } | ||
848 | |||
849 | /* Get access to first message in receive queue */ | ||
850 | |||
851 | buf = skb_peek(&sock->sk->sk_receive_queue); | ||
852 | msg = buf_msg(buf); | ||
853 | sz = msg_data_sz(msg); | ||
854 | err = msg_errcode(msg); | ||
855 | |||
856 | /* Complete connection setup for an implied connect */ | ||
857 | |||
858 | if (unlikely(sock->state == SS_CONNECTING)) { | ||
859 | if ((res = auto_connect(sock, tsock, msg))) | ||
860 | goto exit; | ||
861 | } | ||
862 | |||
863 | /* Discard an empty non-errored message & try again */ | ||
864 | |||
865 | if ((!sz) && (!err)) { | ||
866 | advance_queue(tsock); | ||
867 | goto restart; | ||
868 | } | ||
869 | |||
870 | /* Capture sender's address (optional) */ | ||
871 | |||
872 | set_orig_addr(m, msg); | ||
873 | |||
874 | /* Capture ancillary data (optional) */ | ||
875 | |||
876 | if ((res = anc_data_recv(m, msg, tsock->p))) | ||
877 | goto exit; | ||
878 | |||
879 | /* Capture message data (if valid) & compute return value (always) */ | ||
880 | |||
881 | if (!err) { | ||
882 | if (unlikely(buf_len < sz)) { | ||
883 | sz = buf_len; | ||
884 | m->msg_flags |= MSG_TRUNC; | ||
885 | } | ||
886 | if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg), | ||
887 | sz))) { | ||
888 | res = -EFAULT; | ||
889 | goto exit; | ||
890 | } | ||
891 | res = sz; | ||
892 | } else { | ||
893 | if ((sock->state == SS_READY) || | ||
894 | ((err == TIPC_CONN_SHUTDOWN) || m->msg_control)) | ||
895 | res = 0; | ||
896 | else | ||
897 | res = -ECONNRESET; | ||
898 | } | ||
899 | |||
900 | /* Consume received message (optional) */ | ||
901 | |||
902 | if (likely(!(flags & MSG_PEEK))) { | ||
903 | if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) | ||
904 | tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked); | ||
905 | advance_queue(tsock); | ||
906 | } | ||
907 | exit: | ||
908 | up(&tsock->sem); | ||
909 | return res; | ||
910 | } | ||
911 | |||
912 | /** | ||
913 | * recv_stream - receive stream-oriented data | ||
914 | * @iocb: (unused) | ||
915 | * @m: descriptor for message info | ||
916 | * @buf_len: total size of user buffer area | ||
917 | * @flags: receive flags | ||
918 | * | ||
919 | * Used for SOCK_STREAM messages only. If not enough data is available | ||
920 | * will optionally wait for more; never truncates data. | ||
921 | * | ||
922 | * Returns size of returned message data, errno otherwise | ||
923 | */ | ||
924 | |||
925 | static int recv_stream(struct kiocb *iocb, struct socket *sock, | ||
926 | struct msghdr *m, size_t buf_len, int flags) | ||
927 | { | ||
928 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
929 | struct sk_buff *buf; | ||
930 | struct tipc_msg *msg; | ||
931 | unsigned int q_len; | ||
932 | unsigned int sz; | ||
933 | int sz_to_copy; | ||
934 | int sz_copied = 0; | ||
935 | int needed; | ||
936 | char *crs = m->msg_iov->iov_base; | ||
937 | unsigned char *buf_crs; | ||
938 | u32 err; | ||
939 | int res; | ||
940 | |||
941 | /* Currently doesn't support receiving into multiple iovec entries */ | ||
942 | |||
943 | if (m->msg_iovlen != 1) | ||
944 | return -EOPNOTSUPP; | ||
945 | |||
946 | /* Catch invalid receive attempts */ | ||
947 | |||
948 | if (unlikely(!buf_len)) | ||
949 | return -EINVAL; | ||
950 | |||
951 | if (unlikely(sock->state == SS_DISCONNECTING)) { | ||
952 | if (skb_queue_len(&sock->sk->sk_receive_queue) == 0) | ||
953 | return -ENOTCONN; | ||
954 | } else if (unlikely(sock->state != SS_CONNECTED)) | ||
955 | return -ENOTCONN; | ||
956 | |||
957 | /* Look for a message in receive queue; wait if necessary */ | ||
958 | |||
959 | if (unlikely(down_interruptible(&tsock->sem))) | ||
960 | return -ERESTARTSYS; | ||
961 | |||
962 | restart: | ||
963 | if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && | ||
964 | (flags & MSG_DONTWAIT))) { | ||
965 | res = (sz_copied == 0) ? -EWOULDBLOCK : 0; | ||
966 | goto exit; | ||
967 | } | ||
968 | |||
969 | if ((res = wait_event_interruptible( | ||
970 | *sock->sk->sk_sleep, | ||
971 | ((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) || | ||
972 | (sock->state == SS_DISCONNECTING))) )) { | ||
973 | goto exit; | ||
974 | } | ||
975 | |||
976 | /* Catch attempt to receive on an already terminated connection */ | ||
977 | /* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */ | ||
978 | |||
979 | if (!q_len) { | ||
980 | res = -ENOTCONN; | ||
981 | goto exit; | ||
982 | } | ||
983 | |||
984 | /* Get access to first message in receive queue */ | ||
985 | |||
986 | buf = skb_peek(&sock->sk->sk_receive_queue); | ||
987 | msg = buf_msg(buf); | ||
988 | sz = msg_data_sz(msg); | ||
989 | err = msg_errcode(msg); | ||
990 | |||
991 | /* Discard an empty non-errored message & try again */ | ||
992 | |||
993 | if ((!sz) && (!err)) { | ||
994 | advance_queue(tsock); | ||
995 | goto restart; | ||
996 | } | ||
997 | |||
998 | /* Optionally capture sender's address & ancillary data of first msg */ | ||
999 | |||
1000 | if (sz_copied == 0) { | ||
1001 | set_orig_addr(m, msg); | ||
1002 | if ((res = anc_data_recv(m, msg, tsock->p))) | ||
1003 | goto exit; | ||
1004 | } | ||
1005 | |||
1006 | /* Capture message data (if valid) & compute return value (always) */ | ||
1007 | |||
1008 | if (!err) { | ||
1009 | buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle); | ||
1010 | sz = buf->tail - buf_crs; | ||
1011 | |||
1012 | needed = (buf_len - sz_copied); | ||
1013 | sz_to_copy = (sz <= needed) ? sz : needed; | ||
1014 | if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) { | ||
1015 | res = -EFAULT; | ||
1016 | goto exit; | ||
1017 | } | ||
1018 | sz_copied += sz_to_copy; | ||
1019 | |||
1020 | if (sz_to_copy < sz) { | ||
1021 | if (!(flags & MSG_PEEK)) | ||
1022 | TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy; | ||
1023 | goto exit; | ||
1024 | } | ||
1025 | |||
1026 | crs += sz_to_copy; | ||
1027 | } else { | ||
1028 | if (sz_copied != 0) | ||
1029 | goto exit; /* can't add error msg to valid data */ | ||
1030 | |||
1031 | if ((err == TIPC_CONN_SHUTDOWN) || m->msg_control) | ||
1032 | res = 0; | ||
1033 | else | ||
1034 | res = -ECONNRESET; | ||
1035 | } | ||
1036 | |||
1037 | /* Consume received message (optional) */ | ||
1038 | |||
1039 | if (likely(!(flags & MSG_PEEK))) { | ||
1040 | if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) | ||
1041 | tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked); | ||
1042 | advance_queue(tsock); | ||
1043 | } | ||
1044 | |||
1045 | /* Loop around if more data is required */ | ||
1046 | |||
1047 | if ((sz_copied < buf_len) /* didn't get all requested data */ | ||
1048 | && (flags & MSG_WAITALL) /* ... and need to wait for more */ | ||
1049 | && (!(flags & MSG_PEEK)) /* ... and aren't just peeking at data */ | ||
1050 | && (!err) /* ... and haven't reached a FIN */ | ||
1051 | ) | ||
1052 | goto restart; | ||
1053 | |||
1054 | exit: | ||
1055 | up(&tsock->sem); | ||
1056 | return res ? res : sz_copied; | ||
1057 | } | ||
1058 | |||
1059 | /** | ||
1060 | * queue_overloaded - test if queue overload condition exists | ||
1061 | * @queue_size: current size of queue | ||
1062 | * @base: nominal maximum size of queue | ||
1063 | * @msg: message to be added to queue | ||
1064 | * | ||
1065 | * Returns 1 if queue is currently overloaded, 0 otherwise | ||
1066 | */ | ||
1067 | |||
1068 | static int queue_overloaded(u32 queue_size, u32 base, struct tipc_msg *msg) | ||
1069 | { | ||
1070 | u32 threshold; | ||
1071 | u32 imp = msg_importance(msg); | ||
1072 | |||
1073 | if (imp == TIPC_LOW_IMPORTANCE) | ||
1074 | threshold = base; | ||
1075 | else if (imp == TIPC_MEDIUM_IMPORTANCE) | ||
1076 | threshold = base * 2; | ||
1077 | else if (imp == TIPC_HIGH_IMPORTANCE) | ||
1078 | threshold = base * 100; | ||
1079 | else | ||
1080 | return 0; | ||
1081 | |||
1082 | if (msg_connected(msg)) | ||
1083 | threshold *= 4; | ||
1084 | |||
1085 | return (queue_size > threshold); | ||
1086 | } | ||
1087 | |||
1088 | /** | ||
1089 | * async_disconnect - wrapper function used to disconnect port | ||
1090 | * @portref: TIPC port reference (passed as pointer-sized value) | ||
1091 | */ | ||
1092 | |||
1093 | static void async_disconnect(unsigned long portref) | ||
1094 | { | ||
1095 | tipc_disconnect((u32)portref); | ||
1096 | } | ||
1097 | |||
1098 | /** | ||
1099 | * dispatch - handle arriving message | ||
1100 | * @tport: TIPC port that received message | ||
1101 | * @buf: message | ||
1102 | * | ||
1103 | * Called with port locked. Must not take socket lock to avoid deadlock risk. | ||
1104 | * | ||
1105 | * Returns TIPC error status code (TIPC_OK if message is not to be rejected) | ||
1106 | */ | ||
1107 | |||
1108 | static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf) | ||
1109 | { | ||
1110 | struct tipc_msg *msg = buf_msg(buf); | ||
1111 | struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle; | ||
1112 | struct socket *sock; | ||
1113 | u32 recv_q_len; | ||
1114 | |||
1115 | /* Reject message if socket is closing */ | ||
1116 | |||
1117 | if (!tsock) | ||
1118 | return TIPC_ERR_NO_PORT; | ||
1119 | |||
1120 | /* Reject message if it is wrong sort of message for socket */ | ||
1121 | |||
1122 | /* | ||
1123 | * WOULD IT BE BETTER TO JUST DISCARD THESE MESSAGES INSTEAD? | ||
1124 | * "NO PORT" ISN'T REALLY THE RIGHT ERROR CODE, AND THERE MAY | ||
1125 | * BE SECURITY IMPLICATIONS INHERENT IN REJECTING INVALID TRAFFIC | ||
1126 | */ | ||
1127 | sock = tsock->sk.sk_socket; | ||
1128 | if (sock->state == SS_READY) { | ||
1129 | if (msg_connected(msg)) { | ||
1130 | msg_dbg(msg, "dispatch filter 1\n"); | ||
1131 | return TIPC_ERR_NO_PORT; | ||
1132 | } | ||
1133 | } else { | ||
1134 | if (msg_mcast(msg)) { | ||
1135 | msg_dbg(msg, "dispatch filter 2\n"); | ||
1136 | return TIPC_ERR_NO_PORT; | ||
1137 | } | ||
1138 | if (sock->state == SS_CONNECTED) { | ||
1139 | if (!msg_connected(msg)) { | ||
1140 | msg_dbg(msg, "dispatch filter 3\n"); | ||
1141 | return TIPC_ERR_NO_PORT; | ||
1142 | } | ||
1143 | } | ||
1144 | else if (sock->state == SS_CONNECTING) { | ||
1145 | if (!msg_connected(msg) && (msg_errcode(msg) == 0)) { | ||
1146 | msg_dbg(msg, "dispatch filter 4\n"); | ||
1147 | return TIPC_ERR_NO_PORT; | ||
1148 | } | ||
1149 | } | ||
1150 | else if (sock->state == SS_LISTENING) { | ||
1151 | if (msg_connected(msg) || msg_errcode(msg)) { | ||
1152 | msg_dbg(msg, "dispatch filter 5\n"); | ||
1153 | return TIPC_ERR_NO_PORT; | ||
1154 | } | ||
1155 | } | ||
1156 | else if (sock->state == SS_DISCONNECTING) { | ||
1157 | msg_dbg(msg, "dispatch filter 6\n"); | ||
1158 | return TIPC_ERR_NO_PORT; | ||
1159 | } | ||
1160 | else /* (sock->state == SS_UNCONNECTED) */ { | ||
1161 | if (msg_connected(msg) || msg_errcode(msg)) { | ||
1162 | msg_dbg(msg, "dispatch filter 7\n"); | ||
1163 | return TIPC_ERR_NO_PORT; | ||
1164 | } | ||
1165 | } | ||
1166 | } | ||
1167 | |||
1168 | /* Reject message if there isn't room to queue it */ | ||
1169 | |||
1170 | if (unlikely((u32)atomic_read(&tipc_queue_size) > | ||
1171 | OVERLOAD_LIMIT_BASE)) { | ||
1172 | if (queue_overloaded(atomic_read(&tipc_queue_size), | ||
1173 | OVERLOAD_LIMIT_BASE, msg)) | ||
1174 | return TIPC_ERR_OVERLOAD; | ||
1175 | } | ||
1176 | recv_q_len = skb_queue_len(&tsock->sk.sk_receive_queue); | ||
1177 | if (unlikely(recv_q_len > (OVERLOAD_LIMIT_BASE / 2))) { | ||
1178 | if (queue_overloaded(recv_q_len, | ||
1179 | OVERLOAD_LIMIT_BASE / 2, msg)) | ||
1180 | return TIPC_ERR_OVERLOAD; | ||
1181 | } | ||
1182 | |||
1183 | /* Initiate connection termination for an incoming 'FIN' */ | ||
1184 | |||
1185 | if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) { | ||
1186 | sock->state = SS_DISCONNECTING; | ||
1187 | /* Note: Use signal since port lock is already taken! */ | ||
1188 | k_signal((Handler)async_disconnect, tport->ref); | ||
1189 | } | ||
1190 | |||
1191 | /* Enqueue message (finally!) */ | ||
1192 | |||
1193 | msg_dbg(msg,"<DISP<: "); | ||
1194 | TIPC_SKB_CB(buf)->handle = msg_data(msg); | ||
1195 | atomic_inc(&tipc_queue_size); | ||
1196 | skb_queue_tail(&sock->sk->sk_receive_queue, buf); | ||
1197 | |||
1198 | wake_up_interruptible(sock->sk->sk_sleep); | ||
1199 | return TIPC_OK; | ||
1200 | } | ||
1201 | |||
1202 | /** | ||
1203 | * wakeupdispatch - wake up port after congestion | ||
1204 | * @tport: port to wakeup | ||
1205 | * | ||
1206 | * Called with port lock on. | ||
1207 | */ | ||
1208 | |||
1209 | static void wakeupdispatch(struct tipc_port *tport) | ||
1210 | { | ||
1211 | struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle; | ||
1212 | |||
1213 | wake_up_interruptible(tsock->sk.sk_sleep); | ||
1214 | } | ||
1215 | |||
1216 | /** | ||
1217 | * connect - establish a connection to another TIPC port | ||
1218 | * @sock: socket structure | ||
1219 | * @dest: socket address for destination port | ||
1220 | * @destlen: size of socket address data structure | ||
1221 | * @flags: (unused) | ||
1222 | * | ||
1223 | * Returns 0 on success, errno otherwise | ||
1224 | */ | ||
1225 | |||
1226 | static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | ||
1227 | int flags) | ||
1228 | { | ||
1229 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
1230 | struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; | ||
1231 | struct msghdr m = {0,}; | ||
1232 | struct sk_buff *buf; | ||
1233 | struct tipc_msg *msg; | ||
1234 | int res; | ||
1235 | |||
1236 | /* For now, TIPC does not allow use of connect() with DGRAM or RDM types */ | ||
1237 | |||
1238 | if (sock->state == SS_READY) | ||
1239 | return -EOPNOTSUPP; | ||
1240 | |||
1241 | /* MOVE THE REST OF THIS ERROR CHECKING TO send_msg()? */ | ||
1242 | if (sock->state == SS_LISTENING) | ||
1243 | return -EOPNOTSUPP; | ||
1244 | if (sock->state == SS_CONNECTING) | ||
1245 | return -EALREADY; | ||
1246 | if (sock->state != SS_UNCONNECTED) | ||
1247 | return -EISCONN; | ||
1248 | |||
1249 | if ((dst->family != AF_TIPC) || | ||
1250 | ((dst->addrtype != TIPC_ADDR_NAME) && (dst->addrtype != TIPC_ADDR_ID))) | ||
1251 | return -EINVAL; | ||
1252 | |||
1253 | /* Send a 'SYN-' to destination */ | ||
1254 | |||
1255 | m.msg_name = dest; | ||
1256 | if ((res = send_msg(0, sock, &m, 0)) < 0) { | ||
1257 | sock->state = SS_DISCONNECTING; | ||
1258 | return res; | ||
1259 | } | ||
1260 | |||
1261 | if (down_interruptible(&tsock->sem)) | ||
1262 | return -ERESTARTSYS; | ||
1263 | |||
1264 | /* Wait for destination's 'ACK' response */ | ||
1265 | |||
1266 | res = wait_event_interruptible_timeout(*sock->sk->sk_sleep, | ||
1267 | skb_queue_len(&sock->sk->sk_receive_queue), | ||
1268 | sock->sk->sk_rcvtimeo); | ||
1269 | buf = skb_peek(&sock->sk->sk_receive_queue); | ||
1270 | if (res > 0) { | ||
1271 | msg = buf_msg(buf); | ||
1272 | res = auto_connect(sock, tsock, msg); | ||
1273 | if (!res) { | ||
1274 | if (dst->addrtype == TIPC_ADDR_NAME) { | ||
1275 | tsock->p->conn_type = dst->addr.name.name.type; | ||
1276 | tsock->p->conn_instance = dst->addr.name.name.instance; | ||
1277 | } | ||
1278 | if (!msg_data_sz(msg)) | ||
1279 | advance_queue(tsock); | ||
1280 | } | ||
1281 | } else { | ||
1282 | if (res == 0) { | ||
1283 | res = -ETIMEDOUT; | ||
1284 | } else | ||
1285 | { /* leave "res" unchanged */ } | ||
1286 | sock->state = SS_DISCONNECTING; | ||
1287 | } | ||
1288 | |||
1289 | up(&tsock->sem); | ||
1290 | return res; | ||
1291 | } | ||
1292 | |||
1293 | /** | ||
1294 | * listen - allow socket to listen for incoming connections | ||
1295 | * @sock: socket structure | ||
1296 | * @len: (unused) | ||
1297 | * | ||
1298 | * Returns 0 on success, errno otherwise | ||
1299 | */ | ||
1300 | |||
1301 | static int listen(struct socket *sock, int len) | ||
1302 | { | ||
1303 | /* REQUIRES SOCKET LOCKING OF SOME SORT? */ | ||
1304 | |||
1305 | if (sock->state == SS_READY) | ||
1306 | return -EOPNOTSUPP; | ||
1307 | if (sock->state != SS_UNCONNECTED) | ||
1308 | return -EINVAL; | ||
1309 | sock->state = SS_LISTENING; | ||
1310 | return 0; | ||
1311 | } | ||
1312 | |||
1313 | /** | ||
1314 | * accept - wait for connection request | ||
1315 | * @sock: listening socket | ||
1316 | * @newsock: new socket that is to be connected | ||
1317 | * @flags: file-related flags associated with socket | ||
1318 | * | ||
1319 | * Returns 0 on success, errno otherwise | ||
1320 | */ | ||
1321 | |||
1322 | static int accept(struct socket *sock, struct socket *newsock, int flags) | ||
1323 | { | ||
1324 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
1325 | struct sk_buff *buf; | ||
1326 | int res = -EFAULT; | ||
1327 | |||
1328 | if (sock->state == SS_READY) | ||
1329 | return -EOPNOTSUPP; | ||
1330 | if (sock->state != SS_LISTENING) | ||
1331 | return -EINVAL; | ||
1332 | |||
1333 | if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && | ||
1334 | (flags & O_NONBLOCK))) | ||
1335 | return -EWOULDBLOCK; | ||
1336 | |||
1337 | if (down_interruptible(&tsock->sem)) | ||
1338 | return -ERESTARTSYS; | ||
1339 | |||
1340 | if (wait_event_interruptible(*sock->sk->sk_sleep, | ||
1341 | skb_queue_len(&sock->sk->sk_receive_queue))) { | ||
1342 | res = -ERESTARTSYS; | ||
1343 | goto exit; | ||
1344 | } | ||
1345 | buf = skb_peek(&sock->sk->sk_receive_queue); | ||
1346 | |||
1347 | res = tipc_create(newsock, 0); | ||
1348 | if (!res) { | ||
1349 | struct tipc_sock *new_tsock = tipc_sk(newsock->sk); | ||
1350 | struct tipc_portid id; | ||
1351 | struct tipc_msg *msg = buf_msg(buf); | ||
1352 | u32 new_ref = new_tsock->p->ref; | ||
1353 | |||
1354 | id.ref = msg_origport(msg); | ||
1355 | id.node = msg_orignode(msg); | ||
1356 | tipc_connect2port(new_ref, &id); | ||
1357 | newsock->state = SS_CONNECTED; | ||
1358 | |||
1359 | tipc_set_portimportance(new_ref, msg_importance(msg)); | ||
1360 | if (msg_named(msg)) { | ||
1361 | new_tsock->p->conn_type = msg_nametype(msg); | ||
1362 | new_tsock->p->conn_instance = msg_nameinst(msg); | ||
1363 | } | ||
1364 | |||
1365 | /* | ||
1366 | * Respond to 'SYN-' by discarding it & returning 'ACK'-. | ||
1367 | * Respond to 'SYN+' by queuing it on new socket. | ||
1368 | */ | ||
1369 | |||
1370 | msg_dbg(msg,"<ACC<: "); | ||
1371 | if (!msg_data_sz(msg)) { | ||
1372 | struct msghdr m = {0,}; | ||
1373 | |||
1374 | send_packet(0, newsock, &m, 0); | ||
1375 | advance_queue(tsock); | ||
1376 | } else { | ||
1377 | sock_lock(tsock); | ||
1378 | skb_dequeue(&sock->sk->sk_receive_queue); | ||
1379 | sock_unlock(tsock); | ||
1380 | skb_queue_head(&newsock->sk->sk_receive_queue, buf); | ||
1381 | } | ||
1382 | } | ||
1383 | exit: | ||
1384 | up(&tsock->sem); | ||
1385 | return res; | ||
1386 | } | ||
1387 | |||
1388 | /** | ||
1389 | * shutdown - shutdown socket connection | ||
1390 | * @sock: socket structure | ||
1391 | * @how: direction to close (always treated as read + write) | ||
1392 | * | ||
1393 | * Terminates connection (if necessary), then purges socket's receive queue. | ||
1394 | * | ||
1395 | * Returns 0 on success, errno otherwise | ||
1396 | */ | ||
1397 | |||
1398 | static int shutdown(struct socket *sock, int how) | ||
1399 | { | ||
1400 | struct tipc_sock* tsock = tipc_sk(sock->sk); | ||
1401 | struct sk_buff *buf; | ||
1402 | int res; | ||
1403 | |||
1404 | /* Could return -EINVAL for an invalid "how", but why bother? */ | ||
1405 | |||
1406 | if (down_interruptible(&tsock->sem)) | ||
1407 | return -ERESTARTSYS; | ||
1408 | |||
1409 | sock_lock(tsock); | ||
1410 | |||
1411 | switch (sock->state) { | ||
1412 | case SS_CONNECTED: | ||
1413 | |||
1414 | /* Send 'FIN+' or 'FIN-' message to peer */ | ||
1415 | |||
1416 | sock_unlock(tsock); | ||
1417 | restart: | ||
1418 | if ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) { | ||
1419 | atomic_dec(&tipc_queue_size); | ||
1420 | if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) { | ||
1421 | buf_discard(buf); | ||
1422 | goto restart; | ||
1423 | } | ||
1424 | tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN); | ||
1425 | } | ||
1426 | else { | ||
1427 | tipc_shutdown(tsock->p->ref); | ||
1428 | } | ||
1429 | sock_lock(tsock); | ||
1430 | |||
1431 | /* fall through */ | ||
1432 | |||
1433 | case SS_DISCONNECTING: | ||
1434 | |||
1435 | /* Discard any unreceived messages */ | ||
1436 | |||
1437 | while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) { | ||
1438 | atomic_dec(&tipc_queue_size); | ||
1439 | buf_discard(buf); | ||
1440 | } | ||
1441 | tsock->p->conn_unacked = 0; | ||
1442 | |||
1443 | /* fall through */ | ||
1444 | |||
1445 | case SS_CONNECTING: | ||
1446 | sock->state = SS_DISCONNECTING; | ||
1447 | res = 0; | ||
1448 | break; | ||
1449 | |||
1450 | default: | ||
1451 | res = -ENOTCONN; | ||
1452 | } | ||
1453 | |||
1454 | sock_unlock(tsock); | ||
1455 | |||
1456 | up(&tsock->sem); | ||
1457 | return res; | ||
1458 | } | ||
1459 | |||
1460 | /** | ||
1461 | * setsockopt - set socket option | ||
1462 | * @sock: socket structure | ||
1463 | * @lvl: option level | ||
1464 | * @opt: option identifier | ||
1465 | * @ov: pointer to new option value | ||
1466 | * @ol: length of option value | ||
1467 | * | ||
1468 | * For stream sockets only, accepts and ignores all IPPROTO_TCP options | ||
1469 | * (to ease compatibility). | ||
1470 | * | ||
1471 | * Returns 0 on success, errno otherwise | ||
1472 | */ | ||
1473 | |||
1474 | static int setsockopt(struct socket *sock, int lvl, int opt, char *ov, int ol) | ||
1475 | { | ||
1476 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
1477 | u32 value; | ||
1478 | int res; | ||
1479 | |||
1480 | if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) | ||
1481 | return 0; | ||
1482 | if (lvl != SOL_TIPC) | ||
1483 | return -ENOPROTOOPT; | ||
1484 | if (ol < sizeof(value)) | ||
1485 | return -EINVAL; | ||
1486 | if ((res = get_user(value, (u32 *)ov))) | ||
1487 | return res; | ||
1488 | |||
1489 | if (down_interruptible(&tsock->sem)) | ||
1490 | return -ERESTARTSYS; | ||
1491 | |||
1492 | switch (opt) { | ||
1493 | case TIPC_IMPORTANCE: | ||
1494 | res = tipc_set_portimportance(tsock->p->ref, value); | ||
1495 | break; | ||
1496 | case TIPC_SRC_DROPPABLE: | ||
1497 | if (sock->type != SOCK_STREAM) | ||
1498 | res = tipc_set_portunreliable(tsock->p->ref, value); | ||
1499 | else | ||
1500 | res = -ENOPROTOOPT; | ||
1501 | break; | ||
1502 | case TIPC_DEST_DROPPABLE: | ||
1503 | res = tipc_set_portunreturnable(tsock->p->ref, value); | ||
1504 | break; | ||
1505 | case TIPC_CONN_TIMEOUT: | ||
1506 | sock->sk->sk_rcvtimeo = (value * HZ / 1000); | ||
1507 | break; | ||
1508 | default: | ||
1509 | res = -EINVAL; | ||
1510 | } | ||
1511 | |||
1512 | up(&tsock->sem); | ||
1513 | return res; | ||
1514 | } | ||
1515 | |||
1516 | /** | ||
1517 | * getsockopt - get socket option | ||
1518 | * @sock: socket structure | ||
1519 | * @lvl: option level | ||
1520 | * @opt: option identifier | ||
1521 | * @ov: receptacle for option value | ||
1522 | * @ol: receptacle for length of option value | ||
1523 | * | ||
1524 | * For stream sockets only, returns 0 length result for all IPPROTO_TCP options | ||
1525 | * (to ease compatibility). | ||
1526 | * | ||
1527 | * Returns 0 on success, errno otherwise | ||
1528 | */ | ||
1529 | |||
1530 | static int getsockopt(struct socket *sock, int lvl, int opt, char *ov, int *ol) | ||
1531 | { | ||
1532 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
1533 | int len; | ||
1534 | u32 value; | ||
1535 | int res; | ||
1536 | |||
1537 | if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) | ||
1538 | return put_user(0, ol); | ||
1539 | if (lvl != SOL_TIPC) | ||
1540 | return -ENOPROTOOPT; | ||
1541 | if ((res = get_user(len, ol))) | ||
1542 | return res; | ||
1543 | |||
1544 | if (down_interruptible(&tsock->sem)) | ||
1545 | return -ERESTARTSYS; | ||
1546 | |||
1547 | switch (opt) { | ||
1548 | case TIPC_IMPORTANCE: | ||
1549 | res = tipc_portimportance(tsock->p->ref, &value); | ||
1550 | break; | ||
1551 | case TIPC_SRC_DROPPABLE: | ||
1552 | res = tipc_portunreliable(tsock->p->ref, &value); | ||
1553 | break; | ||
1554 | case TIPC_DEST_DROPPABLE: | ||
1555 | res = tipc_portunreturnable(tsock->p->ref, &value); | ||
1556 | break; | ||
1557 | case TIPC_CONN_TIMEOUT: | ||
1558 | value = (sock->sk->sk_rcvtimeo * 1000) / HZ; | ||
1559 | break; | ||
1560 | default: | ||
1561 | res = -EINVAL; | ||
1562 | } | ||
1563 | |||
1564 | if (res) { | ||
1565 | /* "get" failed */ | ||
1566 | } | ||
1567 | else if (len < sizeof(value)) { | ||
1568 | res = -EINVAL; | ||
1569 | } | ||
1570 | else if ((res = copy_to_user(ov, &value, sizeof(value)))) { | ||
1571 | /* couldn't return value */ | ||
1572 | } | ||
1573 | else { | ||
1574 | res = put_user(sizeof(value), ol); | ||
1575 | } | ||
1576 | |||
1577 | up(&tsock->sem); | ||
1578 | return res; | ||
1579 | } | ||
1580 | |||
1581 | /** | ||
1582 | * Placeholders for non-implemented functionality | ||
1583 | * | ||
1584 | * Returns error code (POSIX-compliant where defined) | ||
1585 | */ | ||
1586 | |||
1587 | static int ioctl(struct socket *s, u32 cmd, unsigned long arg) | ||
1588 | { | ||
1589 | return -EINVAL; | ||
1590 | } | ||
1591 | |||
1592 | static int no_mmap(struct file *file, struct socket *sock, | ||
1593 | struct vm_area_struct *vma) | ||
1594 | { | ||
1595 | return -EINVAL; | ||
1596 | } | ||
1597 | static ssize_t no_sendpage(struct socket *sock, struct page *page, | ||
1598 | int offset, size_t size, int flags) | ||
1599 | { | ||
1600 | return -EINVAL; | ||
1601 | } | ||
1602 | |||
1603 | static int no_skpair(struct socket *s1, struct socket *s2) | ||
1604 | { | ||
1605 | return -EOPNOTSUPP; | ||
1606 | } | ||
1607 | |||
1608 | /** | ||
1609 | * Protocol switches for the various types of TIPC sockets | ||
1610 | */ | ||
1611 | |||
1612 | static struct proto_ops msg_ops = { | ||
1613 | .owner = THIS_MODULE, | ||
1614 | .family = AF_TIPC, | ||
1615 | .release = release, | ||
1616 | .bind = bind, | ||
1617 | .connect = connect, | ||
1618 | .socketpair = no_skpair, | ||
1619 | .accept = accept, | ||
1620 | .getname = get_name, | ||
1621 | .poll = poll, | ||
1622 | .ioctl = ioctl, | ||
1623 | .listen = listen, | ||
1624 | .shutdown = shutdown, | ||
1625 | .setsockopt = setsockopt, | ||
1626 | .getsockopt = getsockopt, | ||
1627 | .sendmsg = send_msg, | ||
1628 | .recvmsg = recv_msg, | ||
1629 | .mmap = no_mmap, | ||
1630 | .sendpage = no_sendpage | ||
1631 | }; | ||
1632 | |||
1633 | static struct proto_ops packet_ops = { | ||
1634 | .owner = THIS_MODULE, | ||
1635 | .family = AF_TIPC, | ||
1636 | .release = release, | ||
1637 | .bind = bind, | ||
1638 | .connect = connect, | ||
1639 | .socketpair = no_skpair, | ||
1640 | .accept = accept, | ||
1641 | .getname = get_name, | ||
1642 | .poll = poll, | ||
1643 | .ioctl = ioctl, | ||
1644 | .listen = listen, | ||
1645 | .shutdown = shutdown, | ||
1646 | .setsockopt = setsockopt, | ||
1647 | .getsockopt = getsockopt, | ||
1648 | .sendmsg = send_packet, | ||
1649 | .recvmsg = recv_msg, | ||
1650 | .mmap = no_mmap, | ||
1651 | .sendpage = no_sendpage | ||
1652 | }; | ||
1653 | |||
1654 | static struct proto_ops stream_ops = { | ||
1655 | .owner = THIS_MODULE, | ||
1656 | .family = AF_TIPC, | ||
1657 | .release = release, | ||
1658 | .bind = bind, | ||
1659 | .connect = connect, | ||
1660 | .socketpair = no_skpair, | ||
1661 | .accept = accept, | ||
1662 | .getname = get_name, | ||
1663 | .poll = poll, | ||
1664 | .ioctl = ioctl, | ||
1665 | .listen = listen, | ||
1666 | .shutdown = shutdown, | ||
1667 | .setsockopt = setsockopt, | ||
1668 | .getsockopt = getsockopt, | ||
1669 | .sendmsg = send_stream, | ||
1670 | .recvmsg = recv_stream, | ||
1671 | .mmap = no_mmap, | ||
1672 | .sendpage = no_sendpage | ||
1673 | }; | ||
1674 | |||
1675 | static struct net_proto_family tipc_family_ops = { | ||
1676 | .owner = THIS_MODULE, | ||
1677 | .family = AF_TIPC, | ||
1678 | .create = tipc_create | ||
1679 | }; | ||
1680 | |||
1681 | static struct proto tipc_proto = { | ||
1682 | .name = "TIPC", | ||
1683 | .owner = THIS_MODULE, | ||
1684 | .obj_size = sizeof(struct tipc_sock) | ||
1685 | }; | ||
1686 | |||
1687 | /** | ||
1688 | * socket_init - initialize TIPC socket interface | ||
1689 | * | ||
1690 | * Returns 0 on success, errno otherwise | ||
1691 | */ | ||
1692 | int socket_init(void) | ||
1693 | { | ||
1694 | int res; | ||
1695 | |||
1696 | res = proto_register(&tipc_proto, 1); | ||
1697 | if (res) { | ||
1698 | err("Failed to register TIPC protocol type\n"); | ||
1699 | goto out; | ||
1700 | } | ||
1701 | |||
1702 | res = sock_register(&tipc_family_ops); | ||
1703 | if (res) { | ||
1704 | err("Failed to register TIPC socket type\n"); | ||
1705 | proto_unregister(&tipc_proto); | ||
1706 | goto out; | ||
1707 | } | ||
1708 | |||
1709 | sockets_enabled = 1; | ||
1710 | out: | ||
1711 | return res; | ||
1712 | } | ||
1713 | |||
1714 | /** | ||
1715 | * sock_stop - stop TIPC socket interface | ||
1716 | */ | ||
1717 | void socket_stop(void) | ||
1718 | { | ||
1719 | if (!sockets_enabled) | ||
1720 | return; | ||
1721 | |||
1722 | sockets_enabled = 0; | ||
1723 | sock_unregister(tipc_family_ops.family); | ||
1724 | proto_unregister(&tipc_proto); | ||
1725 | } | ||
1726 | |||
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c new file mode 100644 index 000000000000..80e219ba527d --- /dev/null +++ b/net/tipc/subscr.c | |||
@@ -0,0 +1,527 @@ | |||
1 | /* | ||
2 | * net/tipc/subscr.c: TIPC subscription service | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "dbg.h" | ||
39 | #include "subscr.h" | ||
40 | #include "name_table.h" | ||
41 | #include "ref.h" | ||
42 | |||
43 | /** | ||
44 | * struct subscriber - TIPC network topology subscriber | ||
45 | * @ref: object reference to subscriber object itself | ||
46 | * @lock: pointer to spinlock controlling access to subscriber object | ||
47 | * @subscriber_list: adjacent subscribers in top. server's list of subscribers | ||
48 | * @subscription_list: list of subscription objects for this subscriber | ||
49 | * @port_ref: object reference to port used to communicate with subscriber | ||
50 | * @swap: indicates if subscriber uses opposite endianness in its messages | ||
51 | */ | ||
52 | |||
53 | struct subscriber { | ||
54 | u32 ref; | ||
55 | spinlock_t *lock; | ||
56 | struct list_head subscriber_list; | ||
57 | struct list_head subscription_list; | ||
58 | u32 port_ref; | ||
59 | int swap; | ||
60 | }; | ||
61 | |||
62 | /** | ||
63 | * struct top_srv - TIPC network topology subscription service | ||
64 | * @user_ref: TIPC userid of subscription service | ||
65 | * @setup_port: reference to TIPC port that handles subscription requests | ||
66 | * @subscription_count: number of active subscriptions (not subscribers!) | ||
67 | * @subscriber_list: list of ports subscribing to service | ||
68 | * @lock: spinlock govering access to subscriber list | ||
69 | */ | ||
70 | |||
71 | struct top_srv { | ||
72 | u32 user_ref; | ||
73 | u32 setup_port; | ||
74 | atomic_t subscription_count; | ||
75 | struct list_head subscriber_list; | ||
76 | spinlock_t lock; | ||
77 | }; | ||
78 | |||
79 | static struct top_srv topsrv = { 0 }; | ||
80 | |||
81 | /** | ||
82 | * htohl - convert value to endianness used by destination | ||
83 | * @in: value to convert | ||
84 | * @swap: non-zero if endianness must be reversed | ||
85 | * | ||
86 | * Returns converted value | ||
87 | */ | ||
88 | |||
89 | static inline u32 htohl(u32 in, int swap) | ||
90 | { | ||
91 | char *c = (char *)∈ | ||
92 | |||
93 | return swap ? ((c[3] << 3) + (c[2] << 2) + (c[1] << 1) + c[0]) : in; | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * subscr_send_event - send a message containing a tipc_event to the subscriber | ||
98 | */ | ||
99 | |||
100 | static void subscr_send_event(struct subscription *sub, | ||
101 | u32 found_lower, | ||
102 | u32 found_upper, | ||
103 | u32 event, | ||
104 | u32 port_ref, | ||
105 | u32 node) | ||
106 | { | ||
107 | struct iovec msg_sect; | ||
108 | |||
109 | msg_sect.iov_base = (void *)&sub->evt; | ||
110 | msg_sect.iov_len = sizeof(struct tipc_event); | ||
111 | |||
112 | sub->evt.event = htohl(event, sub->owner->swap); | ||
113 | sub->evt.found_lower = htohl(found_lower, sub->owner->swap); | ||
114 | sub->evt.found_upper = htohl(found_upper, sub->owner->swap); | ||
115 | sub->evt.port.ref = htohl(port_ref, sub->owner->swap); | ||
116 | sub->evt.port.node = htohl(node, sub->owner->swap); | ||
117 | tipc_send(sub->owner->port_ref, 1, &msg_sect); | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * subscr_overlap - test for subscription overlap with the given values | ||
122 | * | ||
123 | * Returns 1 if there is overlap, otherwise 0. | ||
124 | */ | ||
125 | |||
126 | int subscr_overlap(struct subscription *sub, | ||
127 | u32 found_lower, | ||
128 | u32 found_upper) | ||
129 | |||
130 | { | ||
131 | if (found_lower < sub->seq.lower) | ||
132 | found_lower = sub->seq.lower; | ||
133 | if (found_upper > sub->seq.upper) | ||
134 | found_upper = sub->seq.upper; | ||
135 | if (found_lower > found_upper) | ||
136 | return 0; | ||
137 | return 1; | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * subscr_report_overlap - issue event if there is subscription overlap | ||
142 | * | ||
143 | * Protected by nameseq.lock in name_table.c | ||
144 | */ | ||
145 | |||
146 | void subscr_report_overlap(struct subscription *sub, | ||
147 | u32 found_lower, | ||
148 | u32 found_upper, | ||
149 | u32 event, | ||
150 | u32 port_ref, | ||
151 | u32 node, | ||
152 | int must) | ||
153 | { | ||
154 | dbg("Rep overlap %u:%u,%u<->%u,%u\n", sub->seq.type, sub->seq.lower, | ||
155 | sub->seq.upper, found_lower, found_upper); | ||
156 | if (!subscr_overlap(sub, found_lower, found_upper)) | ||
157 | return; | ||
158 | if (!must && (sub->filter != TIPC_SUB_PORTS)) | ||
159 | return; | ||
160 | subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * subscr_timeout - subscription timeout has occurred | ||
165 | */ | ||
166 | |||
167 | static void subscr_timeout(struct subscription *sub) | ||
168 | { | ||
169 | struct subscriber *subscriber; | ||
170 | u32 subscriber_ref; | ||
171 | |||
172 | /* Validate subscriber reference (in case subscriber is terminating) */ | ||
173 | |||
174 | subscriber_ref = sub->owner->ref; | ||
175 | subscriber = (struct subscriber *)ref_lock(subscriber_ref); | ||
176 | if (subscriber == NULL) | ||
177 | return; | ||
178 | |||
179 | /* Unlink subscription from name table */ | ||
180 | |||
181 | nametbl_unsubscribe(sub); | ||
182 | |||
183 | /* Notify subscriber of timeout, then unlink subscription */ | ||
184 | |||
185 | subscr_send_event(sub, | ||
186 | sub->evt.s.seq.lower, | ||
187 | sub->evt.s.seq.upper, | ||
188 | TIPC_SUBSCR_TIMEOUT, | ||
189 | 0, | ||
190 | 0); | ||
191 | list_del(&sub->subscription_list); | ||
192 | |||
193 | /* Now destroy subscription */ | ||
194 | |||
195 | ref_unlock(subscriber_ref); | ||
196 | k_term_timer(&sub->timer); | ||
197 | kfree(sub); | ||
198 | atomic_dec(&topsrv.subscription_count); | ||
199 | } | ||
200 | |||
201 | /** | ||
202 | * subscr_terminate - terminate communication with a subscriber | ||
203 | * | ||
204 | * Called with subscriber locked. Routine must temporarily release this lock | ||
205 | * to enable subscription timeout routine(s) to finish without deadlocking; | ||
206 | * the lock is then reclaimed to allow caller to release it upon return. | ||
207 | * (This should work even in the unlikely event some other thread creates | ||
208 | * a new object reference in the interim that uses this lock; this routine will | ||
209 | * simply wait for it to be released, then claim it.) | ||
210 | */ | ||
211 | |||
212 | static void subscr_terminate(struct subscriber *subscriber) | ||
213 | { | ||
214 | struct subscription *sub; | ||
215 | struct subscription *sub_temp; | ||
216 | |||
217 | /* Invalidate subscriber reference */ | ||
218 | |||
219 | ref_discard(subscriber->ref); | ||
220 | spin_unlock_bh(subscriber->lock); | ||
221 | |||
222 | /* Destroy any existing subscriptions for subscriber */ | ||
223 | |||
224 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, | ||
225 | subscription_list) { | ||
226 | if (sub->timeout != TIPC_WAIT_FOREVER) { | ||
227 | k_cancel_timer(&sub->timer); | ||
228 | k_term_timer(&sub->timer); | ||
229 | } | ||
230 | nametbl_unsubscribe(sub); | ||
231 | list_del(&sub->subscription_list); | ||
232 | dbg("Term: Removed sub %u,%u,%u from subscriber %x list\n", | ||
233 | sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); | ||
234 | kfree(sub); | ||
235 | atomic_dec(&topsrv.subscription_count); | ||
236 | } | ||
237 | |||
238 | /* Sever connection to subscriber */ | ||
239 | |||
240 | tipc_shutdown(subscriber->port_ref); | ||
241 | tipc_deleteport(subscriber->port_ref); | ||
242 | |||
243 | /* Remove subscriber from topology server's subscriber list */ | ||
244 | |||
245 | spin_lock_bh(&topsrv.lock); | ||
246 | list_del(&subscriber->subscriber_list); | ||
247 | spin_unlock_bh(&topsrv.lock); | ||
248 | |||
249 | /* Now destroy subscriber */ | ||
250 | |||
251 | spin_lock_bh(subscriber->lock); | ||
252 | kfree(subscriber); | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * subscr_subscribe - create subscription for subscriber | ||
257 | * | ||
258 | * Called with subscriber locked | ||
259 | */ | ||
260 | |||
261 | static void subscr_subscribe(struct tipc_subscr *s, | ||
262 | struct subscriber *subscriber) | ||
263 | { | ||
264 | struct subscription *sub; | ||
265 | |||
266 | /* Refuse subscription if global limit exceeded */ | ||
267 | |||
268 | if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) { | ||
269 | warn("Failed: max %u subscriptions\n", tipc_max_subscriptions); | ||
270 | subscr_terminate(subscriber); | ||
271 | return; | ||
272 | } | ||
273 | |||
274 | /* Allocate subscription object */ | ||
275 | |||
276 | sub = kmalloc(sizeof(*sub), GFP_ATOMIC); | ||
277 | if (sub == NULL) { | ||
278 | warn("Memory squeeze; ignoring subscription\n"); | ||
279 | subscr_terminate(subscriber); | ||
280 | return; | ||
281 | } | ||
282 | |||
283 | /* Determine/update subscriber's endianness */ | ||
284 | |||
285 | if ((s->filter == TIPC_SUB_PORTS) || (s->filter == TIPC_SUB_SERVICE)) | ||
286 | subscriber->swap = 0; | ||
287 | else | ||
288 | subscriber->swap = 1; | ||
289 | |||
290 | /* Initialize subscription object */ | ||
291 | |||
292 | memset(sub, 0, sizeof(*sub)); | ||
293 | sub->seq.type = htohl(s->seq.type, subscriber->swap); | ||
294 | sub->seq.lower = htohl(s->seq.lower, subscriber->swap); | ||
295 | sub->seq.upper = htohl(s->seq.upper, subscriber->swap); | ||
296 | sub->timeout = htohl(s->timeout, subscriber->swap); | ||
297 | sub->filter = htohl(s->filter, subscriber->swap); | ||
298 | if ((((sub->filter != TIPC_SUB_PORTS) | ||
299 | && (sub->filter != TIPC_SUB_SERVICE))) | ||
300 | || (sub->seq.lower > sub->seq.upper)) { | ||
301 | warn("Rejecting illegal subscription %u,%u,%u\n", | ||
302 | sub->seq.type, sub->seq.lower, sub->seq.upper); | ||
303 | kfree(sub); | ||
304 | subscr_terminate(subscriber); | ||
305 | return; | ||
306 | } | ||
307 | memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); | ||
308 | INIT_LIST_HEAD(&sub->subscription_list); | ||
309 | INIT_LIST_HEAD(&sub->nameseq_list); | ||
310 | list_add(&sub->subscription_list, &subscriber->subscription_list); | ||
311 | atomic_inc(&topsrv.subscription_count); | ||
312 | if (sub->timeout != TIPC_WAIT_FOREVER) { | ||
313 | k_init_timer(&sub->timer, | ||
314 | (Handler)subscr_timeout, (unsigned long)sub); | ||
315 | k_start_timer(&sub->timer, sub->timeout); | ||
316 | } | ||
317 | sub->owner = subscriber; | ||
318 | nametbl_subscribe(sub); | ||
319 | } | ||
320 | |||
321 | /** | ||
322 | * subscr_conn_shutdown_event - handle termination request from subscriber | ||
323 | */ | ||
324 | |||
325 | static void subscr_conn_shutdown_event(void *usr_handle, | ||
326 | u32 portref, | ||
327 | struct sk_buff **buf, | ||
328 | unsigned char const *data, | ||
329 | unsigned int size, | ||
330 | int reason) | ||
331 | { | ||
332 | struct subscriber *subscriber; | ||
333 | spinlock_t *subscriber_lock; | ||
334 | |||
335 | subscriber = ref_lock((u32)(unsigned long)usr_handle); | ||
336 | if (subscriber == NULL) | ||
337 | return; | ||
338 | |||
339 | subscriber_lock = subscriber->lock; | ||
340 | subscr_terminate(subscriber); | ||
341 | spin_unlock_bh(subscriber_lock); | ||
342 | } | ||
343 | |||
344 | /** | ||
345 | * subscr_conn_msg_event - handle new subscription request from subscriber | ||
346 | */ | ||
347 | |||
348 | static void subscr_conn_msg_event(void *usr_handle, | ||
349 | u32 port_ref, | ||
350 | struct sk_buff **buf, | ||
351 | const unchar *data, | ||
352 | u32 size) | ||
353 | { | ||
354 | struct subscriber *subscriber; | ||
355 | spinlock_t *subscriber_lock; | ||
356 | |||
357 | subscriber = ref_lock((u32)(unsigned long)usr_handle); | ||
358 | if (subscriber == NULL) | ||
359 | return; | ||
360 | |||
361 | subscriber_lock = subscriber->lock; | ||
362 | if (size != sizeof(struct tipc_subscr)) | ||
363 | subscr_terminate(subscriber); | ||
364 | else | ||
365 | subscr_subscribe((struct tipc_subscr *)data, subscriber); | ||
366 | |||
367 | spin_unlock_bh(subscriber_lock); | ||
368 | } | ||
369 | |||
370 | /** | ||
371 | * subscr_named_msg_event - handle request to establish a new subscriber | ||
372 | */ | ||
373 | |||
374 | static void subscr_named_msg_event(void *usr_handle, | ||
375 | u32 port_ref, | ||
376 | struct sk_buff **buf, | ||
377 | const unchar *data, | ||
378 | u32 size, | ||
379 | u32 importance, | ||
380 | struct tipc_portid const *orig, | ||
381 | struct tipc_name_seq const *dest) | ||
382 | { | ||
383 | struct subscriber *subscriber; | ||
384 | struct iovec msg_sect = {0, 0}; | ||
385 | spinlock_t *subscriber_lock; | ||
386 | |||
387 | dbg("subscr_named_msg_event: orig = %x own = %x,\n", | ||
388 | orig->node, tipc_own_addr); | ||
389 | if (size && (size != sizeof(struct tipc_subscr))) { | ||
390 | warn("Received tipc_subscr of invalid size\n"); | ||
391 | return; | ||
392 | } | ||
393 | |||
394 | /* Create subscriber object */ | ||
395 | |||
396 | subscriber = kmalloc(sizeof(struct subscriber), GFP_ATOMIC); | ||
397 | if (subscriber == NULL) { | ||
398 | warn("Memory squeeze; ignoring subscriber setup\n"); | ||
399 | return; | ||
400 | } | ||
401 | memset(subscriber, 0, sizeof(struct subscriber)); | ||
402 | INIT_LIST_HEAD(&subscriber->subscription_list); | ||
403 | INIT_LIST_HEAD(&subscriber->subscriber_list); | ||
404 | subscriber->ref = ref_acquire(subscriber, &subscriber->lock); | ||
405 | if (subscriber->ref == 0) { | ||
406 | warn("Failed to acquire subscriber reference\n"); | ||
407 | kfree(subscriber); | ||
408 | return; | ||
409 | } | ||
410 | |||
411 | /* Establish a connection to subscriber */ | ||
412 | |||
413 | tipc_createport(topsrv.user_ref, | ||
414 | (void *)(unsigned long)subscriber->ref, | ||
415 | importance, | ||
416 | 0, | ||
417 | 0, | ||
418 | subscr_conn_shutdown_event, | ||
419 | 0, | ||
420 | 0, | ||
421 | subscr_conn_msg_event, | ||
422 | 0, | ||
423 | &subscriber->port_ref); | ||
424 | if (subscriber->port_ref == 0) { | ||
425 | warn("Memory squeeze; failed to create subscription port\n"); | ||
426 | ref_discard(subscriber->ref); | ||
427 | kfree(subscriber); | ||
428 | return; | ||
429 | } | ||
430 | tipc_connect2port(subscriber->port_ref, orig); | ||
431 | |||
432 | |||
433 | /* Add subscriber to topology server's subscriber list */ | ||
434 | |||
435 | ref_lock(subscriber->ref); | ||
436 | spin_lock_bh(&topsrv.lock); | ||
437 | list_add(&subscriber->subscriber_list, &topsrv.subscriber_list); | ||
438 | spin_unlock_bh(&topsrv.lock); | ||
439 | |||
440 | /* | ||
441 | * Subscribe now if message contains a subscription, | ||
442 | * otherwise send an empty response to complete connection handshaking | ||
443 | */ | ||
444 | |||
445 | subscriber_lock = subscriber->lock; | ||
446 | if (size) | ||
447 | subscr_subscribe((struct tipc_subscr *)data, subscriber); | ||
448 | else | ||
449 | tipc_send(subscriber->port_ref, 1, &msg_sect); | ||
450 | |||
451 | spin_unlock_bh(subscriber_lock); | ||
452 | } | ||
453 | |||
454 | int subscr_start(void) | ||
455 | { | ||
456 | struct tipc_name_seq seq = {TIPC_TOP_SRV, TIPC_TOP_SRV, TIPC_TOP_SRV}; | ||
457 | int res = -1; | ||
458 | |||
459 | memset(&topsrv, 0, sizeof (topsrv)); | ||
460 | topsrv.lock = SPIN_LOCK_UNLOCKED; | ||
461 | INIT_LIST_HEAD(&topsrv.subscriber_list); | ||
462 | |||
463 | spin_lock_bh(&topsrv.lock); | ||
464 | res = tipc_attach(&topsrv.user_ref, 0, 0); | ||
465 | if (res) { | ||
466 | spin_unlock_bh(&topsrv.lock); | ||
467 | return res; | ||
468 | } | ||
469 | |||
470 | res = tipc_createport(topsrv.user_ref, | ||
471 | 0, | ||
472 | TIPC_CRITICAL_IMPORTANCE, | ||
473 | 0, | ||
474 | 0, | ||
475 | 0, | ||
476 | 0, | ||
477 | subscr_named_msg_event, | ||
478 | 0, | ||
479 | 0, | ||
480 | &topsrv.setup_port); | ||
481 | if (res) | ||
482 | goto failed; | ||
483 | |||
484 | res = nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq); | ||
485 | if (res) | ||
486 | goto failed; | ||
487 | |||
488 | spin_unlock_bh(&topsrv.lock); | ||
489 | return 0; | ||
490 | |||
491 | failed: | ||
492 | err("Failed to create subscription service\n"); | ||
493 | tipc_detach(topsrv.user_ref); | ||
494 | topsrv.user_ref = 0; | ||
495 | spin_unlock_bh(&topsrv.lock); | ||
496 | return res; | ||
497 | } | ||
498 | |||
499 | void subscr_stop(void) | ||
500 | { | ||
501 | struct subscriber *subscriber; | ||
502 | struct subscriber *subscriber_temp; | ||
503 | spinlock_t *subscriber_lock; | ||
504 | |||
505 | if (topsrv.user_ref) { | ||
506 | tipc_deleteport(topsrv.setup_port); | ||
507 | list_for_each_entry_safe(subscriber, subscriber_temp, | ||
508 | &topsrv.subscriber_list, | ||
509 | subscriber_list) { | ||
510 | ref_lock(subscriber->ref); | ||
511 | subscriber_lock = subscriber->lock; | ||
512 | subscr_terminate(subscriber); | ||
513 | spin_unlock_bh(subscriber_lock); | ||
514 | } | ||
515 | tipc_detach(topsrv.user_ref); | ||
516 | topsrv.user_ref = 0; | ||
517 | } | ||
518 | } | ||
519 | |||
520 | |||
521 | int tipc_ispublished(struct tipc_name const *name) | ||
522 | { | ||
523 | u32 domain = 0; | ||
524 | |||
525 | return(nametbl_translate(name->type, name->instance,&domain) != 0); | ||
526 | } | ||
527 | |||
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h new file mode 100644 index 000000000000..ccff4efcb755 --- /dev/null +++ b/net/tipc/subscr.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * net/tipc/subscr.h: Include file for TIPC subscription service | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_SUBSCR_H | ||
38 | #define _TIPC_SUBSCR_H | ||
39 | |||
40 | /** | ||
41 | * struct subscription - TIPC network topology subscription object | ||
42 | * @seq: name sequence associated with subscription | ||
43 | * @timeout: duration of subscription (in ms) | ||
44 | * @filter: event filtering to be done for subscription | ||
45 | * @evt: template for events generated by subscription | ||
46 | * @subscription_list: adjacent subscriptions in subscriber's subscription list | ||
47 | * @nameseq_list: adjacent subscriptions in name sequence's subscription list | ||
48 | * @timer_ref: reference to timer governing subscription duration (may be NULL) | ||
49 | * @owner: pointer to subscriber object associated with this subscription | ||
50 | */ | ||
51 | |||
52 | struct subscription { | ||
53 | struct tipc_name_seq seq; | ||
54 | u32 timeout; | ||
55 | u32 filter; | ||
56 | struct tipc_event evt; | ||
57 | struct list_head subscription_list; | ||
58 | struct list_head nameseq_list; | ||
59 | struct timer_list timer; | ||
60 | struct subscriber *owner; | ||
61 | }; | ||
62 | |||
63 | int subscr_overlap(struct subscription * sub, | ||
64 | u32 found_lower, | ||
65 | u32 found_upper); | ||
66 | |||
67 | void subscr_report_overlap(struct subscription * sub, | ||
68 | u32 found_lower, | ||
69 | u32 found_upper, | ||
70 | u32 event, | ||
71 | u32 port_ref, | ||
72 | u32 node, | ||
73 | int must_report); | ||
74 | |||
75 | int subscr_start(void); | ||
76 | |||
77 | void subscr_stop(void); | ||
78 | |||
79 | |||
80 | #endif | ||
diff --git a/net/tipc/user_reg.c b/net/tipc/user_reg.c new file mode 100644 index 000000000000..35ec7dc8211d --- /dev/null +++ b/net/tipc/user_reg.c | |||
@@ -0,0 +1,265 @@ | |||
1 | /* | ||
2 | * net/tipc/user_reg.c: TIPC user registry code | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "user_reg.h" | ||
39 | |||
40 | /* | ||
41 | * TIPC user registry keeps track of users of the tipc_port interface. | ||
42 | * | ||
43 | * The registry utilizes an array of "TIPC user" entries; | ||
44 | * a user's ID is the index of their associated array entry. | ||
45 | * Array entry 0 is not used, so userid 0 is not valid; | ||
46 | * TIPC sometimes uses this value to denote an anonymous user. | ||
47 | * The list of free entries is initially chained from last entry to entry 1. | ||
48 | */ | ||
49 | |||
50 | /** | ||
51 | * struct tipc_user - registered TIPC user info | ||
52 | * @next: index of next free registry entry (or -1 for an allocated entry) | ||
53 | * @callback: ptr to routine to call when TIPC mode changes (NULL if none) | ||
54 | * @usr_handle: user-defined value passed to callback routine | ||
55 | * @ports: list of user ports owned by the user | ||
56 | */ | ||
57 | |||
58 | struct tipc_user { | ||
59 | int next; | ||
60 | tipc_mode_event callback; | ||
61 | void *usr_handle; | ||
62 | struct list_head ports; | ||
63 | }; | ||
64 | |||
65 | #define MAX_USERID 64 | ||
66 | #define USER_LIST_SIZE ((MAX_USERID + 1) * sizeof(struct tipc_user)) | ||
67 | |||
68 | static struct tipc_user *users = 0; | ||
69 | static u32 next_free_user = MAX_USERID + 1; | ||
70 | static spinlock_t reg_lock = SPIN_LOCK_UNLOCKED; | ||
71 | |||
72 | /** | ||
73 | * reg_init - create TIPC user registry (but don't activate it) | ||
74 | * | ||
75 | * If registry has been pre-initialized it is left "as is". | ||
76 | * NOTE: This routine may be called when TIPC is inactive. | ||
77 | */ | ||
78 | |||
79 | static int reg_init(void) | ||
80 | { | ||
81 | u32 i; | ||
82 | |||
83 | spin_lock_bh(®_lock); | ||
84 | if (!users) { | ||
85 | users = (struct tipc_user *)kmalloc(USER_LIST_SIZE, GFP_ATOMIC); | ||
86 | if (users) { | ||
87 | memset(users, 0, USER_LIST_SIZE); | ||
88 | for (i = 1; i <= MAX_USERID; i++) { | ||
89 | users[i].next = i - 1; | ||
90 | } | ||
91 | next_free_user = MAX_USERID; | ||
92 | } | ||
93 | } | ||
94 | spin_unlock_bh(®_lock); | ||
95 | return users ? TIPC_OK : -ENOMEM; | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * reg_callback - inform TIPC user about current operating mode | ||
100 | */ | ||
101 | |||
102 | static void reg_callback(struct tipc_user *user_ptr) | ||
103 | { | ||
104 | tipc_mode_event cb; | ||
105 | void *arg; | ||
106 | |||
107 | spin_lock_bh(®_lock); | ||
108 | cb = user_ptr->callback; | ||
109 | arg = user_ptr->usr_handle; | ||
110 | spin_unlock_bh(®_lock); | ||
111 | |||
112 | if (cb) | ||
113 | cb(arg, tipc_mode, tipc_own_addr); | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * reg_start - activate TIPC user registry | ||
118 | */ | ||
119 | |||
120 | int reg_start(void) | ||
121 | { | ||
122 | u32 u; | ||
123 | int res; | ||
124 | |||
125 | if ((res = reg_init())) | ||
126 | return res; | ||
127 | |||
128 | for (u = 1; u <= MAX_USERID; u++) { | ||
129 | if (users[u].callback) | ||
130 | k_signal((Handler)reg_callback, | ||
131 | (unsigned long)&users[u]); | ||
132 | } | ||
133 | return TIPC_OK; | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * reg_stop - shut down & delete TIPC user registry | ||
138 | */ | ||
139 | |||
140 | void reg_stop(void) | ||
141 | { | ||
142 | int id; | ||
143 | |||
144 | if (!users) | ||
145 | return; | ||
146 | |||
147 | for (id = 1; id <= MAX_USERID; id++) { | ||
148 | if (users[id].callback) | ||
149 | reg_callback(&users[id]); | ||
150 | } | ||
151 | kfree(users); | ||
152 | users = 0; | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * tipc_attach - register a TIPC user | ||
157 | * | ||
158 | * NOTE: This routine may be called when TIPC is inactive. | ||
159 | */ | ||
160 | |||
161 | int tipc_attach(u32 *userid, tipc_mode_event cb, void *usr_handle) | ||
162 | { | ||
163 | struct tipc_user *user_ptr; | ||
164 | |||
165 | if ((tipc_mode == TIPC_NOT_RUNNING) && !cb) | ||
166 | return -ENOPROTOOPT; | ||
167 | if (!users) | ||
168 | reg_init(); | ||
169 | |||
170 | spin_lock_bh(®_lock); | ||
171 | if (!next_free_user) { | ||
172 | spin_unlock_bh(®_lock); | ||
173 | return -EBUSY; | ||
174 | } | ||
175 | user_ptr = &users[next_free_user]; | ||
176 | *userid = next_free_user; | ||
177 | next_free_user = user_ptr->next; | ||
178 | user_ptr->next = -1; | ||
179 | spin_unlock_bh(®_lock); | ||
180 | |||
181 | user_ptr->callback = cb; | ||
182 | user_ptr->usr_handle = usr_handle; | ||
183 | INIT_LIST_HEAD(&user_ptr->ports); | ||
184 | atomic_inc(&tipc_user_count); | ||
185 | |||
186 | if (cb && (tipc_mode != TIPC_NOT_RUNNING)) | ||
187 | k_signal((Handler)reg_callback, (unsigned long)user_ptr); | ||
188 | return TIPC_OK; | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * tipc_detach - deregister a TIPC user | ||
193 | */ | ||
194 | |||
195 | void tipc_detach(u32 userid) | ||
196 | { | ||
197 | struct tipc_user *user_ptr; | ||
198 | struct list_head ports_temp; | ||
199 | struct user_port *up_ptr, *temp_up_ptr; | ||
200 | |||
201 | if ((userid == 0) || (userid > MAX_USERID)) | ||
202 | return; | ||
203 | |||
204 | spin_lock_bh(®_lock); | ||
205 | if ((!users) || (users[userid].next >= 0)) { | ||
206 | spin_unlock_bh(®_lock); | ||
207 | return; | ||
208 | } | ||
209 | |||
210 | user_ptr = &users[userid]; | ||
211 | user_ptr->callback = NULL; | ||
212 | INIT_LIST_HEAD(&ports_temp); | ||
213 | list_splice(&user_ptr->ports, &ports_temp); | ||
214 | user_ptr->next = next_free_user; | ||
215 | next_free_user = userid; | ||
216 | spin_unlock_bh(®_lock); | ||
217 | |||
218 | atomic_dec(&tipc_user_count); | ||
219 | |||
220 | list_for_each_entry_safe(up_ptr, temp_up_ptr, &ports_temp, uport_list) { | ||
221 | tipc_deleteport(up_ptr->ref); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * reg_add_port - register a user's driver port | ||
227 | */ | ||
228 | |||
229 | int reg_add_port(struct user_port *up_ptr) | ||
230 | { | ||
231 | struct tipc_user *user_ptr; | ||
232 | |||
233 | if (up_ptr->user_ref == 0) | ||
234 | return TIPC_OK; | ||
235 | if (up_ptr->user_ref > MAX_USERID) | ||
236 | return -EINVAL; | ||
237 | if ((tipc_mode == TIPC_NOT_RUNNING) || !users ) | ||
238 | return -ENOPROTOOPT; | ||
239 | |||
240 | spin_lock_bh(®_lock); | ||
241 | user_ptr = &users[up_ptr->user_ref]; | ||
242 | list_add(&up_ptr->uport_list, &user_ptr->ports); | ||
243 | spin_unlock_bh(®_lock); | ||
244 | return TIPC_OK; | ||
245 | } | ||
246 | |||
247 | /** | ||
248 | * reg_remove_port - deregister a user's driver port | ||
249 | */ | ||
250 | |||
251 | int reg_remove_port(struct user_port *up_ptr) | ||
252 | { | ||
253 | if (up_ptr->user_ref == 0) | ||
254 | return TIPC_OK; | ||
255 | if (up_ptr->user_ref > MAX_USERID) | ||
256 | return -EINVAL; | ||
257 | if (!users ) | ||
258 | return -ENOPROTOOPT; | ||
259 | |||
260 | spin_lock_bh(®_lock); | ||
261 | list_del_init(&up_ptr->uport_list); | ||
262 | spin_unlock_bh(®_lock); | ||
263 | return TIPC_OK; | ||
264 | } | ||
265 | |||
diff --git a/net/tipc/user_reg.h b/net/tipc/user_reg.h new file mode 100644 index 000000000000..122ca9be3671 --- /dev/null +++ b/net/tipc/user_reg.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * net/tipc/user_reg.h: Include file for TIPC user registry code | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_USER_REG_H | ||
38 | #define _TIPC_USER_REG_H | ||
39 | |||
40 | #include "port.h" | ||
41 | |||
42 | int reg_start(void); | ||
43 | void reg_stop(void); | ||
44 | |||
45 | int reg_add_port(struct user_port *up_ptr); | ||
46 | int reg_remove_port(struct user_port *up_ptr); | ||
47 | |||
48 | #endif | ||
diff --git a/net/tipc/zone.c b/net/tipc/zone.c new file mode 100644 index 000000000000..4eaef662d568 --- /dev/null +++ b/net/tipc/zone.c | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * net/tipc/zone.c: TIPC zone management routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "zone.h" | ||
39 | #include "net.h" | ||
40 | #include "addr.h" | ||
41 | #include "node_subscr.h" | ||
42 | #include "cluster.h" | ||
43 | #include "node.h" | ||
44 | |||
45 | struct _zone *zone_create(u32 addr) | ||
46 | { | ||
47 | struct _zone *z_ptr = 0; | ||
48 | u32 z_num; | ||
49 | |||
50 | if (!addr_domain_valid(addr)) | ||
51 | return 0; | ||
52 | |||
53 | z_ptr = (struct _zone *)kmalloc(sizeof(*z_ptr), GFP_ATOMIC); | ||
54 | if (z_ptr != NULL) { | ||
55 | memset(z_ptr, 0, sizeof(*z_ptr)); | ||
56 | z_num = tipc_zone(addr); | ||
57 | z_ptr->addr = tipc_addr(z_num, 0, 0); | ||
58 | net.zones[z_num] = z_ptr; | ||
59 | } | ||
60 | return z_ptr; | ||
61 | } | ||
62 | |||
63 | void zone_delete(struct _zone *z_ptr) | ||
64 | { | ||
65 | u32 c_num; | ||
66 | |||
67 | if (!z_ptr) | ||
68 | return; | ||
69 | for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { | ||
70 | cluster_delete(z_ptr->clusters[c_num]); | ||
71 | } | ||
72 | kfree(z_ptr); | ||
73 | } | ||
74 | |||
75 | void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr) | ||
76 | { | ||
77 | u32 c_num = tipc_cluster(c_ptr->addr); | ||
78 | |||
79 | assert(c_ptr->addr); | ||
80 | assert(c_num <= tipc_max_clusters); | ||
81 | assert(z_ptr->clusters[c_num] == 0); | ||
82 | z_ptr->clusters[c_num] = c_ptr; | ||
83 | } | ||
84 | |||
85 | void zone_remove_as_router(struct _zone *z_ptr, u32 router) | ||
86 | { | ||
87 | u32 c_num; | ||
88 | |||
89 | for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { | ||
90 | if (z_ptr->clusters[c_num]) { | ||
91 | cluster_remove_as_router(z_ptr->clusters[c_num], | ||
92 | router); | ||
93 | } | ||
94 | } | ||
95 | } | ||
96 | |||
97 | void zone_send_external_routes(struct _zone *z_ptr, u32 dest) | ||
98 | { | ||
99 | u32 c_num; | ||
100 | |||
101 | for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { | ||
102 | if (z_ptr->clusters[c_num]) { | ||
103 | if (in_own_cluster(z_ptr->addr)) | ||
104 | continue; | ||
105 | cluster_send_ext_routes(z_ptr->clusters[c_num], dest); | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | |||
110 | struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref) | ||
111 | { | ||
112 | struct cluster *c_ptr; | ||
113 | struct node *n_ptr; | ||
114 | u32 c_num; | ||
115 | |||
116 | if (!z_ptr) | ||
117 | return 0; | ||
118 | c_ptr = z_ptr->clusters[tipc_cluster(addr)]; | ||
119 | if (!c_ptr) | ||
120 | return 0; | ||
121 | n_ptr = cluster_select_node(c_ptr, ref); | ||
122 | if (n_ptr) | ||
123 | return n_ptr; | ||
124 | |||
125 | /* Links to any other clusters within this zone ? */ | ||
126 | for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { | ||
127 | c_ptr = z_ptr->clusters[c_num]; | ||
128 | if (!c_ptr) | ||
129 | return 0; | ||
130 | n_ptr = cluster_select_node(c_ptr, ref); | ||
131 | if (n_ptr) | ||
132 | return n_ptr; | ||
133 | } | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref) | ||
138 | { | ||
139 | struct cluster *c_ptr; | ||
140 | u32 c_num; | ||
141 | u32 router; | ||
142 | |||
143 | if (!z_ptr) | ||
144 | return 0; | ||
145 | c_ptr = z_ptr->clusters[tipc_cluster(addr)]; | ||
146 | router = c_ptr ? cluster_select_router(c_ptr, ref) : 0; | ||
147 | if (router) | ||
148 | return router; | ||
149 | |||
150 | /* Links to any other clusters within the zone? */ | ||
151 | for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { | ||
152 | c_ptr = z_ptr->clusters[c_num]; | ||
153 | router = c_ptr ? cluster_select_router(c_ptr, ref) : 0; | ||
154 | if (router) | ||
155 | return router; | ||
156 | } | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | |||
161 | u32 zone_next_node(u32 addr) | ||
162 | { | ||
163 | struct cluster *c_ptr = cluster_find(addr); | ||
164 | |||
165 | if (c_ptr) | ||
166 | return cluster_next_node(c_ptr, addr); | ||
167 | return 0; | ||
168 | } | ||
169 | |||
diff --git a/net/tipc/zone.h b/net/tipc/zone.h new file mode 100644 index 000000000000..4326f78d8292 --- /dev/null +++ b/net/tipc/zone.h | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * net/tipc/zone.h: Include file for TIPC zone management routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_ZONE_H | ||
38 | #define _TIPC_ZONE_H | ||
39 | |||
40 | #include "node_subscr.h" | ||
41 | #include "net.h" | ||
42 | |||
43 | |||
44 | /** | ||
45 | * struct _zone - TIPC zone structure | ||
46 | * @addr: network address of zone | ||
47 | * @clusters: array of pointers to all clusters within zone | ||
48 | * @links: (used for inter-zone communication) | ||
49 | */ | ||
50 | |||
51 | struct _zone { | ||
52 | u32 addr; | ||
53 | struct cluster *clusters[2]; /* currently limited to just 1 cluster */ | ||
54 | u32 links; | ||
55 | }; | ||
56 | |||
57 | struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref); | ||
58 | u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref); | ||
59 | void zone_remove_as_router(struct _zone *z_ptr, u32 router); | ||
60 | void zone_send_external_routes(struct _zone *z_ptr, u32 dest); | ||
61 | struct _zone *zone_create(u32 addr); | ||
62 | void zone_delete(struct _zone *z_ptr); | ||
63 | void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr); | ||
64 | u32 zone_next_node(u32 addr); | ||
65 | |||
66 | static inline struct _zone *zone_find(u32 addr) | ||
67 | { | ||
68 | return net.zones[tipc_zone(addr)]; | ||
69 | } | ||
70 | |||
71 | #endif | ||
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 12e4fb72bf0f..53d6c7bbf564 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -494,8 +494,7 @@ static inline void avc_print_ipv6_addr(struct audit_buffer *ab, | |||
494 | char *name1, char *name2) | 494 | char *name1, char *name2) |
495 | { | 495 | { |
496 | if (!ipv6_addr_any(addr)) | 496 | if (!ipv6_addr_any(addr)) |
497 | audit_log_format(ab, " %s=%04x:%04x:%04x:%04x:%04x:" | 497 | audit_log_format(ab, " %s=" NIP6_FMT, name1, NIP6(*addr)); |
498 | "%04x:%04x:%04x", name1, NIP6(*addr)); | ||
499 | if (port) | 498 | if (port) |
500 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); | 499 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); |
501 | } | 500 | } |
@@ -504,7 +503,7 @@ static inline void avc_print_ipv4_addr(struct audit_buffer *ab, u32 addr, | |||
504 | __be16 port, char *name1, char *name2) | 503 | __be16 port, char *name1, char *name2) |
505 | { | 504 | { |
506 | if (addr) | 505 | if (addr) |
507 | audit_log_format(ab, " %s=%d.%d.%d.%d", name1, NIPQUAD(addr)); | 506 | audit_log_format(ab, " %s=" NIPQUAD_FMT, name1, NIPQUAD(addr)); |
508 | if (port) | 507 | if (port) |
509 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); | 508 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); |
510 | } | 509 | } |