11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version. 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk) 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) Steven Whitehouse GW7RRM (stevew@acm.org) 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de) 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de) 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) Frederic Rible F1OAT (frible@teaser.fr) 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 144fc268d24ceb9f4150777c1b5b2b8e6214e56b2bRandy Dunlap 154fc268d24ceb9f4150777c1b5b2b8e6214e56b2bRandy Dunlap#include <linux/capability.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/socket.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/in.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sockios.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/net.h> 265a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/ax25.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/inet.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/if_arp.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/sock.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fcntl.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/seq_file.h> 40bc3b2d7fb9b014d75ebb79ba371a763dbab5e8cfPaul Gortmaker#include <linux/export.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ax25_route *ax25_route_list; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_RWLOCK(ax25_route_lock); 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ax25_rt_device_down(struct net_device *dev) 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_route *s, *t, *ax25_rt; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 494de211f1a279275c6c67d6e9b6b25513e46b0bb9Jarek Poplawski write_lock_bh(&ax25_route_lock); 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt = ax25_route_list; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (ax25_rt != NULL) { 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s = ax25_rt; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt = ax25_rt->next; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s->dev == dev) { 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25_route_list == s) { 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_route_list = s->next; 58a51482bde22f99c63fbbb57d5d46cc666384e379Jesper Juhl kfree(s->digipeat); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(s); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (t = ax25_route_list; t != NULL; t = t->next) { 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (t->next == s) { 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->next = s->next; 64a51482bde22f99c63fbbb57d5d46cc666384e379Jesper Juhl kfree(s->digipeat); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(s); 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 724de211f1a279275c6c67d6e9b6b25513e46b0bb9Jarek Poplawski write_unlock_bh(&ax25_route_lock); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 75c9266b99e2def0a456766220df09713f8e765891Ralf Baechlestatic int __must_check ax25_rt_add(struct ax25_routes_struct *route) 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_route *ax25_rt; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_dev *ax25_dev; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ax25_dev = ax25_addr_ax25dev(&route->port_addr)) == NULL) 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (route->digi_count > AX25_MAX_DIGIS) 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 864de211f1a279275c6c67d6e9b6b25513e46b0bb9Jarek Poplawski write_lock_bh(&ax25_route_lock); 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt = ax25_route_list; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (ax25_rt != NULL) { 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25cmp(&ax25_rt->callsign, &route->dest_addr) == 0 && 91528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki ax25_rt->dev == ax25_dev->dev) { 92a51482bde22f99c63fbbb57d5d46cc666384e379Jesper Juhl kfree(ax25_rt->digipeat); 93a51482bde22f99c63fbbb57d5d46cc666384e379Jesper Juhl ax25_rt->digipeat = NULL; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (route->digi_count != 0) { 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { 964de211f1a279275c6c67d6e9b6b25513e46b0bb9Jarek Poplawski write_unlock_bh(&ax25_route_lock); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt->digipeat->lastrepeat = -1; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt->digipeat->ndigi = route->digi_count; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < route->digi_count; i++) { 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt->digipeat->repeated[i] = 0; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt->digipeat->calls[i] = route->digi_addr[i]; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1064de211f1a279275c6c67d6e9b6b25513e46b0bb9Jarek Poplawski write_unlock_bh(&ax25_route_lock); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt = ax25_rt->next; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) { 1134de211f1a279275c6c67d6e9b6b25513e46b0bb9Jarek Poplawski write_unlock_bh(&ax25_route_lock); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 117006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle atomic_set(&ax25_rt->refcount, 1); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt->callsign = route->dest_addr; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt->dev = ax25_dev->dev; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt->digipeat = NULL; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt->ip_mode = ' '; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (route->digi_count != 0) { 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { 1244de211f1a279275c6c67d6e9b6b25513e46b0bb9Jarek Poplawski write_unlock_bh(&ax25_route_lock); 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ax25_rt); 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt->digipeat->lastrepeat = -1; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt->digipeat->ndigi = route->digi_count; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < route->digi_count; i++) { 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt->digipeat->repeated[i] = 0; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt->digipeat->calls[i] = route->digi_addr[i]; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt->next = ax25_route_list; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_route_list = ax25_rt; 1374de211f1a279275c6c67d6e9b6b25513e46b0bb9Jarek Poplawski write_unlock_bh(&ax25_route_lock); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 142006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechlevoid __ax25_put_route(ax25_route *ax25_rt) 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 144006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle kfree(ax25_rt->digipeat); 145006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle kfree(ax25_rt); 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax25_rt_del(struct ax25_routes_struct *route) 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_route *s, *t, *ax25_rt; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_dev *ax25_dev; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ax25_dev = ax25_addr_ax25dev(&route->port_addr)) == NULL) 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1564de211f1a279275c6c67d6e9b6b25513e46b0bb9Jarek Poplawski write_lock_bh(&ax25_route_lock); 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt = ax25_route_list; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (ax25_rt != NULL) { 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s = ax25_rt; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt = ax25_rt->next; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s->dev == ax25_dev->dev && 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25cmp(&route->dest_addr, &s->callsign) == 0) { 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25_route_list == s) { 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_route_list = s->next; 166006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle ax25_put_route(s); 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (t = ax25_route_list; t != NULL; t = t->next) { 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (t->next == s) { 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->next = s->next; 171006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle ax25_put_route(s); 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1784de211f1a279275c6c67d6e9b6b25513e46b0bb9Jarek Poplawski write_unlock_bh(&ax25_route_lock); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax25_rt_opt(struct ax25_route_opt_struct *rt_option) 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_route *ax25_rt; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_dev *ax25_dev; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ax25_dev = ax25_addr_ax25dev(&rt_option->port_addr)) == NULL) 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1924de211f1a279275c6c67d6e9b6b25513e46b0bb9Jarek Poplawski write_lock_bh(&ax25_route_lock); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt = ax25_route_list; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (ax25_rt != NULL) { 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25_rt->dev == ax25_dev->dev && 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25cmp(&rt_option->dest_addr, &ax25_rt->callsign) == 0) { 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (rt_option->cmd) { 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case AX25_SET_RT_IPMODE: 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (rt_option->arg) { 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ' ': 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'D': 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'V': 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt->ip_mode = rt_option->arg; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EINVAL; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EINVAL; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt = ax25_rt->next; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 2204de211f1a279275c6c67d6e9b6b25513e46b0bb9Jarek Poplawski write_unlock_bh(&ax25_route_lock); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ax25_rt_ioctl(unsigned int cmd, void __user *arg) 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ax25_route_opt_struct rt_option; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ax25_routes_struct route; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SIOCADDRT: 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&route, arg, sizeof(route))) 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ax25_rt_add(&route); 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SIOCDELRT: 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&route, arg, sizeof(route))) 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ax25_rt_del(&route); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SIOCAX25OPTRT: 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&rt_option, arg, sizeof(rt_option))) 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ax25_rt_opt(&rt_option); 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PROC_FS 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void *ax25_rt_seq_start(struct seq_file *seq, loff_t *pos) 253f16f3026db6fa63cbb0f4a37833562aa999c93e5Eric Dumazet __acquires(ax25_route_lock) 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ax25_route *ax25_rt; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i = 1; 257528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki 258528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki read_lock(&ax25_route_lock); 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*pos == 0) 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SEQ_START_TOKEN; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) { 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i == *pos) 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ax25_rt; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ++i; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void *ax25_rt_seq_next(struct seq_file *seq, void *v, loff_t *pos) 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ++*pos; 274528930b91ee89a05a6264629cf99109652c19ca8YOSHIFUJI Hideaki return (v == SEQ_START_TOKEN) ? ax25_route_list : 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((struct ax25_route *) v)->next; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ax25_rt_seq_stop(struct seq_file *seq, void *v) 279f16f3026db6fa63cbb0f4a37833562aa999c93e5Eric Dumazet __releases(ax25_route_lock) 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds read_unlock(&ax25_route_lock); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax25_rt_seq_show(struct seq_file *seq, void *v) 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 286f75268cd6cbd24e6c70ff1390f4de5d0bb618539Ralf Baechle char buf[11]; 287f75268cd6cbd24e6c70ff1390f4de5d0bb618539Ralf Baechle 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (v == SEQ_START_TOKEN) 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "callsign dev mode digipeaters\n"); 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ax25_route *ax25_rt = v; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char *callsign; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0) 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds callsign = "default"; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 298f75268cd6cbd24e6c70ff1390f4de5d0bb618539Ralf Baechle callsign = ax2asc(buf, &ax25_rt->callsign); 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_printf(seq, "%-9s %-4s", 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds callsign, 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt->dev ? ax25_rt->dev->name : "???"); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ax25_rt->ip_mode) { 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'V': 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, " vc"); 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'D': 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, " dg"); 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, " *"); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25_rt->digipeat != NULL) 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < ax25_rt->digipeat->ndigi; i++) 318f75268cd6cbd24e6c70ff1390f4de5d0bb618539Ralf Baechle seq_printf(seq, " %s", 319f75268cd6cbd24e6c70ff1390f4de5d0bb618539Ralf Baechle ax2asc(buf, &ax25_rt->digipeat->calls[i])); 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "\n"); 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32656b3d975bbce65f655c5612b4822da671f9fd9b2Philippe De Muyterstatic const struct seq_operations ax25_rt_seqops = { 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .start = ax25_rt_seq_start, 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .next = ax25_rt_seq_next, 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .stop = ax25_rt_seq_stop, 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .show = ax25_rt_seq_show, 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax25_rt_info_open(struct inode *inode, struct file *file) 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return seq_open(file, &ax25_rt_seqops); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3389a32144e9d7b4e21341174b1a83b82a82353be86Arjan van de Venconst struct file_operations ax25_route_fops = { 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .open = ax25_rt_info_open, 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read = seq_read, 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .llseek = seq_lseek, 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .release = seq_release, 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Find AX.25 route 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3513f072310d0ca85891323e9d325c37c76de389387Ralf Baechle * Only routes with a reference count of zero can be destroyed. 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 353006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechleax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev) 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_route *ax25_spe_rt = NULL; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_route *ax25_def_rt = NULL; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_route *ax25_rt; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds read_lock(&ax25_route_lock); 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bind to the physical interface we heard them on, or the default 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * route if none is found; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) { 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev == NULL) { 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev != NULL) 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_spe_rt = ax25_rt; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev != NULL) 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_def_rt = ax25_rt; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev == dev) 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_spe_rt = ax25_rt; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev == dev) 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_def_rt = ax25_rt; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt = ax25_def_rt; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25_spe_rt != NULL) 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt = ax25_spe_rt; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25_rt != NULL) 383006f68b84fe19fc5015a8cf838a10d75f91f0218Ralf Baechle ax25_hold_route(ax25_rt); 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds read_unlock(&ax25_route_lock); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ax25_rt; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adjust path: If you specify a default route and want to connect 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a target on the digipeater path but w/o having a special route 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * set before, the path has to be truncated from your target on. 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void ax25_adjust_path(ax25_address *addr, ax25_digi *digipeat) 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int k; 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = 0; k < digipeat->ndigi; k++) { 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25cmp(addr, &digipeat->calls[k]) == 0) 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds digipeat->ndigi = k; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Find which interface to use. 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 41301d7dd0e9f8c5f1888619d2649c7da389232b408Ralf Baechle ax25_uid_assoc *user; 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_route *ax25_rt; 415b3d18f15092a7db2f229cd7bc69fc40eac0774f4Julia Lawall int err = 0; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ax25_rt = ax25_get_route(addr, NULL)) == NULL) 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EHOSTUNREACH; 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) { 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EHOSTUNREACH; 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto put; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 425734004072e05ae81c3cdd0a04ee37868fb09b71eDavid Howells user = ax25_findbyuid(current_euid()); 42601d7dd0e9f8c5f1888619d2649c7da389232b408Ralf Baechle if (user) { 42701d7dd0e9f8c5f1888619d2649c7da389232b408Ralf Baechle ax25->source_addr = user->call; 42801d7dd0e9f8c5f1888619d2649c7da389232b408Ralf Baechle ax25_uid_put(user); 42901d7dd0e9f8c5f1888619d2649c7da389232b408Ralf Baechle } else { 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) { 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EPERM; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto put; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 43401d7dd0e9f8c5f1888619d2649c7da389232b408Ralf Baechle ax25->source_addr = *(ax25_address *)ax25->ax25_dev->dev->dev_addr; 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25_rt->digipeat != NULL) { 4380459d70add3f7ca5d433d4b2334cc6ec9ddab05bArnaldo Carvalho de Melo ax25->digipeat = kmemdup(ax25_rt->digipeat, sizeof(ax25_digi), 4390459d70add3f7ca5d433d4b2334cc6ec9ddab05bArnaldo Carvalho de Melo GFP_ATOMIC); 4400459d70add3f7ca5d433d4b2334cc6ec9ddab05bArnaldo Carvalho de Melo if (ax25->digipeat == NULL) { 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENOMEM; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto put; 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_adjust_path(addr, ax25->digipeat); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ax25->sk != NULL) { 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bh_lock_sock(ax25->sk); 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_reset_flag(ax25->sk, SOCK_ZAPPED); 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bh_unlock_sock(ax25->sk); 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsput: 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_put_route(ax25_rt); 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 456b3d18f15092a7db2f229cd7bc69fc40eac0774f4Julia Lawall return err; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct sk_buff *ax25_rt_build_path(struct sk_buff *skb, ax25_address *src, 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_address *dest, ax25_digi *digi) 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skbn; 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *bp; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = digi->ndigi * AX25_ADDR_LEN; 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb_headroom(skb) < len) { 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((skbn = skb_realloc_headroom(skb, len)) == NULL) { 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_CRIT "AX.25: ax25_dg_build_path - out of memory\n"); 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb->sk != NULL) 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_set_owner_w(skbn, skb->sk); 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4775d0ba55b6486f58cc890918d7167063d83f7fbb4Eric Dumazet consume_skb(skb); 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb = skbn; 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bp = skb_push(skb, len); 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_addr_build(bp, src, dest, digi, AX25_COMMAND, AX25_MODULUS); 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return skb; 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Free all memory associated with routing structures. 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __exit ax25_rt_free(void) 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_route *s, *ax25_rt = ax25_route_list; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4964de211f1a279275c6c67d6e9b6b25513e46b0bb9Jarek Poplawski write_lock_bh(&ax25_route_lock); 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (ax25_rt != NULL) { 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s = ax25_rt; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ax25_rt = ax25_rt->next; 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501a51482bde22f99c63fbbb57d5d46cc666384e379Jesper Juhl kfree(s->digipeat); 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(s); 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5044de211f1a279275c6c67d6e9b6b25513e46b0bb9Jarek Poplawski write_unlock_bh(&ax25_route_lock); 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 506