static inline void write_string(int fd, const char *string) { write_fully(fd, string, strlen(string)); }
// Given a socket that is connected to a peer we read the request and // create an AttachOperation. As the socket is blocking there is potential // for a denial-of-service if the peer does not response. However this happens // after the peer credentials have been checked and in the worst case it just // means that the attach listener thread is blocked. // BsdAttachOperation* BsdAttachListener::read_request(int s) { char ver_str[8]; sprintf(ver_str, "%d", ATTACH_PROTOCOL_VER); // The request is a sequence of strings so we first figure out the // expected count and the maximum possible length of the request. // The request is: // <ver>0<cmd>0<arg>0<arg>0<arg>0 // where <ver> is the protocol version (1), <cmd> is the command // name ("load", "datadump", ...), and <arg> is an argument int expected_str_count = 2 + AttachOperation::arg_count_max; const int max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) + AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1); char buf[max_len]; int str_count = 0; // Read until all (expected) strings have been read, the buffer is // full, or EOF. int off = 0; int left = max_len; do { int n; RESTARTABLE(read(s, buf+off, left), n); if (n == -1) { return NULL; // reset by peer or other error } if (n == 0) { break; } for (int i=0; i<n; i++) { if (buf[off+i] == 0) { // EOS found str_count++; // The first string is <ver> so check it now to // check for protocol mis-match if (str_count == 1) { if ((strlen(buf) != strlen(ver_str)) || (atoi(buf) != ATTACH_PROTOCOL_VER)) { char msg[32]; sprintf(msg, "%d\n", ATTACH_ERROR_BADVERSION); write_fully(s, msg, strlen(msg)); return NULL; } } } } off += n; left -= n; } while (left > 0 && str_count < expected_str_count); if (str_count != expected_str_count) { return NULL; // incomplete request } // parse request ArgumentIterator args(buf, (max_len)-left); // version already checked char* v = args.next(); char* name = args.next(); if (name == NULL || strlen(name) > AttachOperation::name_length_max) { return NULL; } BsdAttachOperation* op = new BsdAttachOperation(name); for (int i=0; i<AttachOperation::arg_count_max; i++) { char* arg = args.next(); if (arg == NULL) { op->set_arg(i, NULL); } else { if (strlen(arg) > AttachOperation::arg_length_max) { delete op; return NULL; } op->set_arg(i, arg); } } op->set_socket(s); return op; }
static void write_colored(int fd, const char *buffer, size_t length) { if (length < 16) { write_fully(fd, buffer, length); return; } size_t space_offsets[3]; int o = find_space_offsets(buffer, length, space_offsets); if (o == 3) { // Log date and device name write_const(fd, COLOR_DARK_WHITE); write_fully(fd, buffer, space_offsets[0]); // Log process name int pos = 0; for (int i = space_offsets[0]; i < space_offsets[0]; i++) { if (buffer[i] == '[') { pos = i; break; } } write_const(fd, COLOR_CYAN); if (pos && buffer[space_offsets[1]-1] == ']') { write_fully(fd, buffer + space_offsets[0], pos - space_offsets[0]); write_const(fd, COLOR_DARK_CYAN); write_fully(fd, buffer + pos, space_offsets[1] - pos); } else { write_fully(fd, buffer + space_offsets[0], space_offsets[1] - space_offsets[0]); } // Log level size_t levelLength = space_offsets[2] - space_offsets[1]; if (levelLength > 4) { const char *normalColor; const char *darkColor; if (levelLength == 9 && memcmp(buffer + space_offsets[1], " <Debug>:", 9) == 0){ normalColor = COLOR_MAGENTA; darkColor = COLOR_DARK_MAGENTA; } else if (levelLength == 11 && memcmp(buffer + space_offsets[1], " <Warning>:", 11) == 0){ normalColor = COLOR_YELLOW; darkColor = COLOR_DARK_YELLOW; } else if (levelLength == 9 && memcmp(buffer + space_offsets[1], " <Error>:", 9) == 0){ normalColor = COLOR_RED; darkColor = COLOR_DARK_RED; } else if (levelLength == 10 && memcmp(buffer + space_offsets[1], " <Notice>:", 10) == 0) { normalColor = COLOR_GREEN; darkColor = COLOR_DARK_GREEN; } else { goto level_unformatted; } write_string(fd, darkColor); write_fully(fd, buffer + space_offsets[1], 2); write_string(fd, normalColor); write_fully(fd, buffer + space_offsets[1] + 2, levelLength - 4); write_string(fd, darkColor); write_fully(fd, buffer + space_offsets[1] + levelLength - 2, 1); write_const(fd, COLOR_DARK_WHITE); write_fully(fd, buffer + space_offsets[1] + levelLength - 1, 1); } else { level_unformatted: write_const(fd, COLOR_RESET); write_fully(fd, buffer + space_offsets[1], levelLength); } write_const(fd, COLOR_RESET); write_fully(fd, buffer + space_offsets[2], length - space_offsets[2]); } else { write_fully(fd, buffer, length); } }