int be_mysql_superuser(void *handle, const char *username) { struct mysql_backend *conf = (struct mysql_backend *)handle; char *query = NULL, *u = NULL; long nrows, ulen; int issuper = FALSE; MYSQL_RES *res = NULL; MYSQL_ROW rowdata; if (!conf || !conf->superquery) return (FALSE); if (mysql_ping(conf->mysql)) { fprintf(stderr, "%s\n", mysql_error(conf->mysql)); if (!auto_connect(conf)) { return (FALSE); } } if ((u = escape(conf, username, &ulen)) == NULL) return (FALSE); if ((query = malloc(strlen(conf->superquery) + ulen + 128)) == NULL) { free(u); return (FALSE); } sprintf(query, conf->superquery, u); free(u); // puts(query); if (mysql_query(conf->mysql, query)) { fprintf(stderr, "%s\n", mysql_error(conf->mysql)); goto out; } res = mysql_store_result(conf->mysql); if ((nrows = mysql_num_rows(res)) != 1) { goto out; } if (mysql_num_fields(res) != 1) { // DEBUG fprintf(stderr, "numfields not ok\n"); goto out; } if ((rowdata = mysql_fetch_row(res)) == NULL) { goto out; } issuper = atoi(rowdata[0]); out: mysql_free_result(res); free(query); return (issuper); }
static int recv_msg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t buf_len, int flags) { struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); struct sk_buff *buf; struct tipc_msg *msg; long timeout; unsigned int sz; u32 err; int res; /* Catch invalid receive requests */ if (unlikely(!buf_len)) return -EINVAL; lock_sock(sk); if (unlikely(sock->state == SS_UNCONNECTED)) { res = -ENOTCONN; goto exit; } /* will be updated in set_orig_addr() if needed */ m->msg_namelen = 0; timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); restart: /* Look for a message in receive queue; wait if necessary */ while (skb_queue_empty(&sk->sk_receive_queue)) { if (sock->state == SS_DISCONNECTING) { res = -ENOTCONN; goto exit; } if (timeout <= 0L) { res = timeout ? timeout : -EWOULDBLOCK; goto exit; } release_sock(sk); timeout = wait_event_interruptible_timeout(*sk_sleep(sk), tipc_rx_ready(sock), timeout); lock_sock(sk); } /* Look at first message in receive queue */ buf = skb_peek(&sk->sk_receive_queue); msg = buf_msg(buf); sz = msg_data_sz(msg); err = msg_errcode(msg); /* Complete connection setup for an implied connect */ if (unlikely(sock->state == SS_CONNECTING)) { res = auto_connect(sock, msg); if (res) goto exit; } /* Discard an empty non-errored message & try again */ if ((!sz) && (!err)) { advance_rx_queue(sk); goto restart; } /* Capture sender's address (optional) */ set_orig_addr(m, msg); /* Capture ancillary data (optional) */ res = anc_data_recv(m, msg, tport); if (res) goto exit; /* Capture message data (if valid) & compute return value (always) */ if (!err) { if (unlikely(buf_len < sz)) { sz = buf_len; m->msg_flags |= MSG_TRUNC; } res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg), m->msg_iov, sz); if (res) goto exit; res = sz; } else { if ((sock->state == SS_READY) || ((err == TIPC_CONN_SHUTDOWN) || m->msg_control)) res = 0; else res = -ECONNRESET; } /* Consume received message (optional) */ if (likely(!(flags & MSG_PEEK))) { if ((sock->state != SS_READY) && (++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) tipc_acknowledge(tport->ref, tport->conn_unacked); advance_rx_queue(sk); } exit: release_sock(sk); return res; }
static int connect(struct socket *sock, struct sockaddr *dest, int destlen, int flags) { struct sock *sk = sock->sk; struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; struct msghdr m = {NULL,}; struct sk_buff *buf; struct tipc_msg *msg; unsigned int timeout; int res; lock_sock(sk); /* For now, TIPC does not allow use of connect() with DGRAM/RDM types */ if (sock->state == SS_READY) { res = -EOPNOTSUPP; goto exit; } /* For now, TIPC does not support the non-blocking form of connect() */ if (flags & O_NONBLOCK) { res = -EOPNOTSUPP; goto exit; } /* Issue Posix-compliant error code if socket is in the wrong state */ if (sock->state == SS_LISTENING) { res = -EOPNOTSUPP; goto exit; } if (sock->state == SS_CONNECTING) { res = -EALREADY; goto exit; } if (sock->state != SS_UNCONNECTED) { res = -EISCONN; goto exit; } /* * Reject connection attempt using multicast address * * Note: send_msg() validates the rest of the address fields, * so there's no need to do it here */ if (dst->addrtype == TIPC_ADDR_MCAST) { res = -EINVAL; goto exit; } /* Reject any messages already in receive queue (very unlikely) */ reject_rx_queue(sk); /* Send a 'SYN-' to destination */ m.msg_name = dest; m.msg_namelen = destlen; res = send_msg(NULL, sock, &m, 0); if (res < 0) goto exit; /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ timeout = tipc_sk(sk)->conn_timeout; release_sock(sk); res = wait_event_interruptible_timeout(*sk_sleep(sk), (!skb_queue_empty(&sk->sk_receive_queue) || (sock->state != SS_CONNECTING)), timeout ? (long)msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT); lock_sock(sk); if (res > 0) { buf = skb_peek(&sk->sk_receive_queue); if (buf != NULL) { msg = buf_msg(buf); res = auto_connect(sock, msg); if (!res) { if (!msg_data_sz(msg)) advance_rx_queue(sk); } } else { if (sock->state == SS_CONNECTED) res = -EISCONN; else res = -ECONNREFUSED; } } else { if (res == 0) res = -ETIMEDOUT; else ; /* leave "res" unchanged */ sock->state = SS_DISCONNECTING; } exit: release_sock(sk); return res; }
/** * filter_connect - Handle all incoming messages for a connection-based socket * @tsock: TIPC socket * @msg: message * * Returns TIPC error status code and socket error status code * once it encounters some errors */ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf) { struct socket *sock = tsock->sk.sk_socket; struct tipc_msg *msg = buf_msg(*buf); struct sock *sk = &tsock->sk; u32 retval = TIPC_ERR_NO_PORT; int res; if (msg_mcast(msg)) return retval; switch ((int)sock->state) { case SS_CONNECTED: /* Accept only connection-based messages sent by peer */ if (msg_connected(msg) && tipc_port_peer_msg(tsock->p, msg)) { if (unlikely(msg_errcode(msg))) { sock->state = SS_DISCONNECTING; __tipc_disconnect(tsock->p); } retval = TIPC_OK; } break; case SS_CONNECTING: /* Accept only ACK or NACK message */ if (unlikely(msg_errcode(msg))) { sock->state = SS_DISCONNECTING; sk->sk_err = ECONNREFUSED; retval = TIPC_OK; break; } if (unlikely(!msg_connected(msg))) break; res = auto_connect(sock, msg); if (res) { sock->state = SS_DISCONNECTING; sk->sk_err = -res; retval = TIPC_OK; break; } /* If an incoming message is an 'ACK-', it should be * discarded here because it doesn't contain useful * data. In addition, we should try to wake up * connect() routine if sleeping. */ if (msg_data_sz(msg) == 0) { kfree_skb(*buf); *buf = NULL; if (waitqueue_active(sk_sleep(sk))) wake_up_interruptible(sk_sleep(sk)); } retval = TIPC_OK; break; case SS_LISTENING: case SS_UNCONNECTED: /* Accept only SYN message */ if (!msg_connected(msg) && !(msg_errcode(msg))) retval = TIPC_OK; break; case SS_DISCONNECTING: break; default: pr_err("Unknown socket state %u\n", sock->state); } return retval; }
static int recv_msg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t buf_len, int flags) { struct tipc_sock *tsock = tipc_sk(sock->sk); struct sk_buff *buf; struct tipc_msg *msg; unsigned int q_len; unsigned int sz; u32 err; int res; /* Currently doesn't support receiving into multiple iovec entries */ if (m->msg_iovlen != 1) return -EOPNOTSUPP; /* Catch invalid receive attempts */ if (unlikely(!buf_len)) return -EINVAL; if (sock->type == SOCK_SEQPACKET) { if (unlikely(sock->state == SS_UNCONNECTED)) return -ENOTCONN; if (unlikely((sock->state == SS_DISCONNECTING) && (skb_queue_len(&sock->sk->sk_receive_queue) == 0))) return -ENOTCONN; } /* Look for a message in receive queue; wait if necessary */ if (unlikely(down_interruptible(&tsock->sem))) return -ERESTARTSYS; restart: if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && (flags & MSG_DONTWAIT))) { res = -EWOULDBLOCK; goto exit; } if ((res = wait_event_interruptible( *sock->sk->sk_sleep, ((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) || (sock->state == SS_DISCONNECTING))) )) { goto exit; } /* Catch attempt to receive on an already terminated connection */ /* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */ if (!q_len) { res = -ENOTCONN; goto exit; } /* Get access to first message in receive queue */ buf = skb_peek(&sock->sk->sk_receive_queue); msg = buf_msg(buf); sz = msg_data_sz(msg); err = msg_errcode(msg); /* Complete connection setup for an implied connect */ if (unlikely(sock->state == SS_CONNECTING)) { if ((res = auto_connect(sock, tsock, msg))) goto exit; } /* Discard an empty non-errored message & try again */ if ((!sz) && (!err)) { advance_queue(tsock); goto restart; } /* Capture sender's address (optional) */ set_orig_addr(m, msg); /* Capture ancillary data (optional) */ if ((res = anc_data_recv(m, msg, tsock->p))) goto exit; /* Capture message data (if valid) & compute return value (always) */ if (!err) { if (unlikely(buf_len < sz)) { sz = buf_len; m->msg_flags |= MSG_TRUNC; } if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg), sz))) { res = -EFAULT; goto exit; } res = sz; } else { if ((sock->state == SS_READY) || ((err == TIPC_CONN_SHUTDOWN) || m->msg_control)) res = 0; else res = -ECONNRESET; } /* Consume received message (optional) */ if (likely(!(flags & MSG_PEEK))) { if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked); advance_queue(tsock); } exit: up(&tsock->sem); return res; }
static int connect(struct socket *sock, struct sockaddr *dest, int destlen, int flags) { struct tipc_sock *tsock = tipc_sk(sock->sk); struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; struct msghdr m = {NULL,}; struct sk_buff *buf; struct tipc_msg *msg; int res; /* For now, TIPC does not allow use of connect() with DGRAM or RDM types */ if (sock->state == SS_READY) return -EOPNOTSUPP; /* Issue Posix-compliant error code if socket is in the wrong state */ if (sock->state == SS_LISTENING) return -EOPNOTSUPP; if (sock->state == SS_CONNECTING) return -EALREADY; if (sock->state != SS_UNCONNECTED) return -EISCONN; /* * Reject connection attempt using multicast address * * Note: send_msg() validates the rest of the address fields, * so there's no need to do it here */ if (dst->addrtype == TIPC_ADDR_MCAST) return -EINVAL; /* Send a 'SYN-' to destination */ m.msg_name = dest; m.msg_namelen = destlen; if ((res = send_msg(NULL, sock, &m, 0)) < 0) { sock->state = SS_DISCONNECTING; return res; } if (down_interruptible(&tsock->sem)) return -ERESTARTSYS; /* Wait for destination's 'ACK' response */ res = wait_event_interruptible_timeout(*sock->sk->sk_sleep, skb_queue_len(&sock->sk->sk_receive_queue), sock->sk->sk_rcvtimeo); buf = skb_peek(&sock->sk->sk_receive_queue); if (res > 0) { msg = buf_msg(buf); res = auto_connect(sock, tsock, msg); if (!res) { if (!msg_data_sz(msg)) advance_queue(tsock); } } else { if (res == 0) { res = -ETIMEDOUT; } else { /* leave "res" unchanged */ } sock->state = SS_DISCONNECTING; } up(&tsock->sem); return res; }
static int connect(struct socket *sock, struct sockaddr *dest, int destlen, int flags) { struct tipc_sock *tsock = tipc_sk(sock->sk); struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; struct msghdr m = {0,}; struct sk_buff *buf; struct tipc_msg *msg; int res; /* For now, TIPC does not allow use of connect() with DGRAM or RDM types */ if (sock->state == SS_READY) return -EOPNOTSUPP; /* MOVE THE REST OF THIS ERROR CHECKING TO send_msg()? */ if (sock->state == SS_LISTENING) return -EOPNOTSUPP; if (sock->state == SS_CONNECTING) return -EALREADY; if (sock->state != SS_UNCONNECTED) return -EISCONN; if ((dst->family != AF_TIPC) || ((dst->addrtype != TIPC_ADDR_NAME) && (dst->addrtype != TIPC_ADDR_ID))) return -EINVAL; /* Send a 'SYN-' to destination */ m.msg_name = dest; if ((res = send_msg(0, sock, &m, 0)) < 0) { sock->state = SS_DISCONNECTING; return res; } if (down_interruptible(&tsock->sem)) return -ERESTARTSYS; /* Wait for destination's 'ACK' response */ res = wait_event_interruptible_timeout(*sock->sk->sk_sleep, skb_queue_len(&sock->sk->sk_receive_queue), sock->sk->sk_rcvtimeo); buf = skb_peek(&sock->sk->sk_receive_queue); if (res > 0) { msg = buf_msg(buf); res = auto_connect(sock, tsock, msg); if (!res) { if (dst->addrtype == TIPC_ADDR_NAME) { tsock->p->conn_type = dst->addr.name.name.type; tsock->p->conn_instance = dst->addr.name.name.instance; } if (!msg_data_sz(msg)) advance_queue(tsock); } } else { if (res == 0) { res = -ETIMEDOUT; } else { /* leave "res" unchanged */ } sock->state = SS_DISCONNECTING; } up(&tsock->sem); return res; }
int be_mysql_aclcheck(void *handle, const char *username, const char *topic, int acc) { struct mysql_backend *conf = (struct mysql_backend *)handle; char *query = NULL, *u = NULL, *v; long ulen; int match = 0; bool bf; MYSQL_RES *res = NULL; MYSQL_ROW rowdata; if (!conf || !conf->aclquery) return (FALSE); if (mysql_ping(conf->mysql)) { fprintf(stderr, "%s\n", mysql_error(conf->mysql)); if (!auto_connect(conf)) { return (FALSE); } } if ((u = escape(conf, username, &ulen)) == NULL) return (FALSE); if ((query = malloc(strlen(conf->aclquery) + ulen + 128)) == NULL) { free(u); return (FALSE); } sprintf(query, conf->aclquery, u, acc); free(u); //_log(LOG_DEBUG, "SQL: %s", query); if (mysql_query(conf->mysql, query)) { _log(LOG_NOTICE, "%s", mysql_error(conf->mysql)); goto out; } res = mysql_store_result(conf->mysql); if (mysql_num_fields(res) != 1) { fprintf(stderr, "numfields not ok\n"); goto out; } while (match == 0 && (rowdata = mysql_fetch_row(res)) != NULL) { if ((v = rowdata[0]) != NULL) { /* Check mosquitto_match_topic. If true, * if true, set match and break out of loop. */ // FIXME: does this need special work for %c and %u ??? mosquitto_topic_matches_sub(v, topic, &bf); match |= bf; _log(LOG_DEBUG, " mysql: topic_matches(%s, %s) == %d", topic, v, bf); } } out: mysql_free_result(res); free(query); return (match); }
char *be_mysql_getuser(void *handle, const char *username, const char *password, int *authenticated) { struct mysql_backend *conf = (struct mysql_backend *)handle; char *query = NULL, *u = NULL, *value = NULL, *v; long nrows, ulen; MYSQL_RES *res = NULL; MYSQL_ROW rowdata; if (!conf || !conf->userquery || !username || !*username) return (NULL); if (mysql_ping(conf->mysql)) { fprintf(stderr, "%s\n", mysql_error(conf->mysql)); if (!auto_connect(conf)) { return (NULL); } } if ((u = escape(conf, username, &ulen)) == NULL) return (NULL); if ((query = malloc(strlen(conf->userquery) + ulen + 128)) == NULL) { free(u); return (NULL); } sprintf(query, conf->userquery, u); free(u); // DEBUG puts(query); if (mysql_query(conf->mysql, query)) { fprintf(stderr, "%s\n", mysql_error(conf->mysql)); goto out; } res = mysql_store_result(conf->mysql); if ((nrows = mysql_num_rows(res)) != 1) { // DEBUG fprintf(stderr, "rowcount = %ld; not ok\n", nrows); goto out; } if (mysql_num_fields(res) != 1) { // DEBUG fprintf(stderr, "numfields not ok\n"); goto out; } if ((rowdata = mysql_fetch_row(res)) == NULL) { goto out; } v = rowdata[0]; value = (v) ? strdup(v) : NULL; out: mysql_free_result(res); free(query); return (value); }