/* * netsniff-ng - the packet sniffing beast * Copyright 2009, 2010 Daniel Borkmann. * Copyright 2013 Tobias Klauser. * Subject to the GPL, version 2. */ #define _BSD_SOURCE #include #include #include #include #include "tprintf.h" #include "die.h" #include "locking.h" #include "built_in.h" #define term_trailing_size 5 #define term_starting_size 3 #define term_curr_size (get_tty_size() - term_trailing_size) static char buffer[1024]; static volatile size_t buffer_use = 0; static struct spinlock buffer_lock; static int get_tty_size(void) { #ifdef TIOCGSIZE struct ttysize ts = {0}; return (ioctl(0, TIOCGSIZE, &ts) == 0 ? ts.ts_cols : DEFAULT_TTY_SIZE); #elif defined(TIOCGWINSZ) struct winsize ts; return (ioctl(0, TIOCGWINSZ, &ts) == 0 ? ts.ws_col : DEFAULT_TTY_SIZE); #else return DEFAULT_TTY_SIZE; #endif } static inline void __tprintf_flush_newline(void) { int i; fputc('\n', stdout); for (i = 0; i < term_starting_size; ++i) fputc(' ', stdout); } static inline int __tprintf_flush_skip(char *buf, int i) { int val = buf[i]; if (val == ' ' || val == ',') return 1; return 0; } static void __tprintf_flush(void) { size_t i; static ssize_t line_count = 0; ssize_t term_len = term_curr_size; for (i = 0; i < buffer_use; ++i) { if (buffer[i] == '\n') { term_len = term_curr_size; line_count = -1; } if (line_count == term_len) { __tprintf_flush_newline(); line_count = term_starting_size; while (i < buffer_use && __tprintf_flush_skip(buffer, i)) i++; } fputc(buffer[i], stdout); line_count++; } fflush(stdout); buffer_use = 0; } void tprintf_flush(void) { spinlock_lock(&buffer_lock); __tprintf_flush(); spinlock_unlock(&buffer_lock); } void tprintf_init(void) { spinlock_init(&buffer_lock); setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); } void tprintf_cleanup(void) { tprintf_flush(); spinlock_destroy(&buffer_lock); } void tprintf(char *msg, ...) { ssize_t ret; ssize_t avail; va_list vl; spinlock_lock(&buffer_lock); avail = sizeof(buffer) - buffer_use; bug_on(avail < 0); va_start(vl, msg); ret = vsnprintf(buffer + buffer_use, avail, msg, vl); va_end(vl); if (ret < 0) panic("vsnprintf screwed up in tprintf!\n"); if ((size_t) ret > sizeof(buffer)) panic("No mem in tprintf left!\n"); if (ret >= avail) { __tprintf_flush(); avail = sizeof(buffer) - buffer_use; bug_on(avail < 0); va_start(vl, msg); ret = vsnprintf(buffer + buffer_use, avail, msg, vl); va_end(vl); if (ret < 0) panic("vsnprintf screwed up in tprintf!\n"); } buffer_use += ret; spinlock_unlock(&buffer_lock); } void tputchar_safe(int c) { unsigned char ch = (unsigned char)(c & 0xff); if (isprint(ch)) tprintf("%c", ch); else tprintf("\\0x%02x", ch); } void tputs_safe(const char *str, size_t len) { while (len--) { tputchar_safe(*str); str++; } } 5space:mode:
authorMark Bloch <markb@mellanox.com>2016-05-18 16:42:43 +0300
committerDoug Ledford <dledford@redhat.com>2016-05-25 15:39:03 -0400
commit492a7e67ff83fc59adb768de25ccaecd33d46beb (patch)
tree80ffff405af42de77fa5accc97513933e9e5a611
parent3b56113016400a4e2b9870c368ebb8080cb5739b (diff)
IB/IPoIB: Allow setting the device address
In IB networks, and specifically in IPoIB/rdmacm traffic, the device address of an IPoIB interface is used as a means to exchange information between nodes needed for communication. Currently an IPoIB interface will always be created with a device address based on its node GUID without a way to change that. This change adds the ability to set the device address of an IPoIB interface by value. We use the set mac address ndo to do that. The flow should be broken down to two: 1) The GID value is already in the GID table, in this case the interface will be able to set carrier up. 2) The GID value is not yet in the GID table, in this case the interface won't try to join the multicast group and will wait (listen on GID_CHANGE event) until the GID is inserted. In order to track those changes, we add a new flag: * IPOIB_FLAG_DEV_ADDR_SET. When set, it means the dev_addr is a based on a value in the gid table. this bit will be cleared upon a dev_addr change triggered by the user and set after validation. Per IB spec the port GUID can't change if the module is loaded. port GUID is the basis for GID at index 0 which is the basis for the default device address of a ipoib interface. The issue is that there are devices that don't follow the spec, they change the port GUID while HCA is powered on, so in order not to break userspace applications. We need to check if the user wanted to control the device address and we assume that if he sets the device address back to be based on GID index 0, he no longer wishs to control it. In order to track this, we add an additional flag: * IPOIB_FLAG_DEV_ADDR_CTRL When setting the device address, there is no validation of the upper twelve bytes of the device address (flags, qpn, subnet prefix) as those bytes are not under the control of the user. Signed-off-by: Mark Bloch <markb@mellanox.com> Reviewed-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Leon Romanovsky <leon@kernel.org> Signed-off-by: Doug Ledford <dledford@redhat.com>