/** * Handles a server kick request. * * @param data the request packet * @param len the length of data * @param cli_addr the address of the sender * @param cli_len the length of cli_addr */ void *c_req_kick_server(char *data, unsigned int len, struct player *pl) { uint32_t target_id; char *reason, *ptr; struct player *target; struct server *s = pl->in_chan->in_server; if (len != 60) { logger(LOG_WARN, "c_req_kick_server, packet has invalid size : %i instead of %i.", len, 60); return NULL; } ptr = data + 24; target_id = ru32(&ptr); target = get_player_by_public_id(s, target_id); if (target != NULL) { send_acknowledge(pl); /* ACK */ if(player_has_privilege(pl, SP_OTHER_SV_KICK, target->in_chan)) { ptr = data + 28; reason = rstaticstring(29, &ptr); logger(LOG_INFO, "Reason for kicking player %s : %s", target->name, reason); s_notify_kick_server(pl, target, reason); remove_player(s, pl); free(reason); } } return NULL; }
/** * Handle a player ban request. * * @param data the request packet * @param len the length of data * @param cli_addr the address of the sender * @param cli_len the length of cli_addr */ void *c_req_ban(char *data, unsigned int len, struct player *pl) { uint32_t ban_id; struct player *target; char *reason, *ptr; uint16_t duration; struct server *s = pl->in_chan->in_server; ptr = data + 24; ban_id = ru32(&ptr); duration = ru16(&ptr); target = get_player_by_public_id(s, ban_id); if (target != NULL) { send_acknowledge(pl); /* ACK */ if(player_has_privilege(pl, SP_ADM_BAN_IP, target->in_chan)) { reason = rstaticstring(29, &ptr); add_ban(s, new_ban(0, target->cli_addr->sin_addr, reason)); logger(LOG_INFO, "Reason for banning player %s : %s", target->name, reason); s_notify_ban(pl, target, duration, reason); remove_player(s, target); free(reason); } } return NULL; }
/** * Handle a packet to create a new registration with a name, password * and server admin flag and associate it to the player. * * @param data the packet * @param len the length of the packet * @param pl the player who issued the request */ void *c_req_register_player(char *data, unsigned int len, struct player *pl) { char *name, *pass; struct registration *reg; struct server *s; unsigned char digest[SHA256_DIGEST_LENGTH]; char *digest_readable, *ptr; struct channel *ch; struct player_channel_privilege *priv; size_t iter, iter2; s = pl->in_chan->in_server; logger(LOG_INFO, "c_req_register_player : registering player"); send_acknowledge(pl); if (player_has_privilege(pl, SP_PL_ALLOW_SELF_REG, NULL) || (pl->global_flags & GLOBAL_FLAG_ALLOWREG)) { logger(LOG_INFO, "c_req_register_player : privileges OK"); ptr = data + 24; name = rstaticstring(29, &ptr); pass = rstaticstring(29, &ptr); if (name == NULL || pass == NULL) { logger(LOG_ERR, "c_req_register_player, strndup failed : %s.", strerror(errno)); if (name != NULL) free(name); if (pass != NULL) free(pass); return NULL; } reg = new_registration(); strcpy(reg->name, name); /* hash the password */ SHA256((unsigned char *)pass, strlen(pass), digest); digest_readable = ustrtohex(digest, SHA256_DIGEST_LENGTH); strcpy(reg->password, digest_readable); free(digest_readable); add_registration(s, reg); /* associate the player with this new registration */ pl->reg = reg; ar_each(struct channel *, ch, iter, s->chans) if (!(ch->flags & CHANNEL_FLAG_UNREGISTERED)) { ar_each(struct player_channel_privilege *, priv, iter2, ch->pl_privileges) if (priv->reg == PL_CH_PRIV_UNREGISTERED && priv->pl_or_reg.pl == pl) { priv->reg = PL_CH_PRIV_REGISTERED; priv->pl_or_reg.reg = reg; } ar_end_each; }
/** * Handles a request to remove a ban. * * @param data the request packet * @param len the length of data * @param cli_addr the address of the sender * @param cli_len the length of cli_addr */ void *c_req_remove_ban(char *data, unsigned int len, struct player *pl) { struct in_addr ip; struct ban *b; struct server *s = pl->in_chan->in_server; if(player_has_privilege(pl, SP_ADM_BAN_IP, NULL)) { send_acknowledge(pl); /* ACK */ inet_aton(data + 24, &ip); b = get_ban_by_ip(s, ip); if (b != NULL) remove_ban(s, b); } return NULL; }
/** * Handles a request to add an IP ban. * * @param data the request packet * @param len the length of data * @param cli_addr the address of the sender * @param cli_len the length of cli_addr */ void *c_req_ip_ban(char *data, unsigned int len, struct player *pl) { struct in_addr ip; uint16_t duration; struct server *s = pl->in_chan->in_server; char *ptr; if(player_has_privilege(pl, SP_ADM_BAN_IP, NULL)) { send_acknowledge(pl); /* ACK */ ptr = data + 24; duration = ru16(&ptr); inet_aton(ptr, &ip); add_ban(s, new_ban(duration, ip, "IP BAN")); } return NULL; }
/** * Handle a packet to create a new registration with a name, password * and server admin flag. * * @param data the packet * @param len the length of the packet * @param pl the player who issued the request */ void *c_req_create_registration(char *data, unsigned int len, struct player *pl) { char *name, *pass; char server_admin; struct registration *reg; struct server *s; unsigned char digest[SHA256_DIGEST_LENGTH]; char *digest_readable, *ptr; s = pl->in_chan->in_server; send_acknowledge(pl); if (player_has_privilege(pl, SP_PL_REGISTER_PLAYER, NULL)) { ptr = data + 24; name = rstaticstring(29, &ptr); pass = rstaticstring(29, &ptr); server_admin = ru8(&ptr); if (name == NULL || pass == NULL) { logger(LOG_ERR, "c_req_create_registration, strndup failed : %s.", strerror(errno)); if (name != NULL) free(name); if (pass != NULL) free(pass); return NULL; } reg = new_registration(); strcpy(reg->name, name); /* hash the password */ SHA256((unsigned char *)pass, strlen(pass), digest); digest_readable = ustrtohex(digest, SHA256_DIGEST_LENGTH); strcpy(reg->password, digest_readable); free(digest_readable); reg->global_flags = server_admin; add_registration(s, reg); /* database callback to insert a new registration */ db_add_registration(s->conf, s, reg); free(name); free(pass); } return NULL; }
//! Send byte and wait for acknowledge if <ackowledge> is true static status_t send_byte(const i2c_bus *bus, uint8 byte, bool acknowledge) { int i; //TRACE("%s: (byte = %x)\n", __func__, byte); for (i = 7; i >= 0; --i) { status_t status = send_bit(bus, byte >> i, i == 7 ? bus->timing.byte_timeout : bus->timing.bit_timeout); if (status != B_OK) return status; } if (acknowledge) return send_acknowledge(bus); return B_OK; }
int cimd_receive_msg(SMSCenter *smsc, Msg **msg) { char *tmpbuff = NULL, *sender = NULL; char *receiver = NULL, *text = NULL, *scts = NULL; char *tmpchar = NULL; debug("bb.sms.cimd", 0, "cimd_receive_smsmessage: starting"); /* the PENDING function has previously requested for the message and checked that it safely found its way into the memory buffer (smsc->buffer) */ /* we want to temporarily store some data */ tmpbuff = gw_malloc(10 * 1024); sender = gw_malloc(10 * 1024); receiver = gw_malloc(10 * 1024); text = gw_malloc(10 * 1024); scts = gw_malloc(10 * 1024); memset(tmpbuff, 0, 10 * 1024); memset(sender, 0, 10 * 1024); memset(receiver, 0, 10 * 1024); memset(text, 0, 10 * 1024); memset(scts, 0, 10 * 1024); /* cut the raw message out from the message buffer */ tmpchar = memchr(smsc->buffer, 0x0A, smsc->buflen); if (tmpchar == NULL) { tmpchar = memchr(smsc->buffer, 0x03, smsc->buflen); if (tmpchar == NULL) goto error; } strncpy(tmpbuff, smsc->buffer, tmpchar - smsc->buffer); smscenter_remove_from_buffer(smsc, tmpchar - smsc->buffer + 1); /* Parse the raw message */ sscanf(tmpbuff, "\x02\x06\tC:05\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t11\x03\x0A", receiver, sender, text, scts); sscanf(tmpbuff, "\x02\x06\tC:05\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t11\x03", receiver, sender, text, scts); /* Translate from the CIMD character set to iso8859-1 */ parse_cimd_to_iso88591(text, tmpbuff, 10*1024); strncpy(text, tmpbuff, 480); /* create a smsmessage structure out of the components */ *msg = msg_create(sms); if (*msg == NULL) return -1; (*msg)->sms.sender = octstr_create(sender); (*msg)->sms.receiver = octstr_create(receiver); (*msg)->sms.msgdata = octstr_create(text); /* Send acknowledge */ send_acknowledge(smsc); /* We got a message so we can instantly check for a new one. */ smsc->cimd_last_spoke -= 5; /* Free and Finish */ gw_free(tmpbuff); gw_free(sender); gw_free(receiver); gw_free(text); gw_free(scts); debug("bb.sms.cimd", 0, "cimd_receive_smsmessage: return ok"); return 1; error: debug("bb.sms.cimd", 0, "cimd_receive_smsmessage: failed"); gw_free(tmpbuff); gw_free(sender); gw_free(receiver); gw_free(text); gw_free(scts); debug("bb.sms.cimd", 0, "cimd_receive_smsmessage: return failed"); return -1; }
/****************************************************************************** * Send a MT message, returns as in smsc_submit_smsmessage in smsc.h */ int cimd_submit_msg(SMSCenter *smsc, Msg *msg) { char *tmpbuff = NULL, *tmptext = NULL; char msgtext[1024]; int ret; int cmd = 0, err = 0; /* Fix these by implementing a could-not-send-because- protocol-does-not-allow in smsc.c or smsgateway.c */ if (octstr_len(msg->sms.msgdata) + octstr_len(msg->sms.udhdata) < 1) { if (msg->sms.msgdata == NULL) msg->sms.msgdata = octstr_create(""); octstr_append_from_hex(msg->sms.msgdata, "20"); } if (octstr_len(msg->sms.sender) < 1) { warning(0, "cimd_submit_smsmessage: ignoring message with 0-length field"); goto okay; /* THIS IS NOT OKAY!!!! XXX */ } if (octstr_len(msg->sms.receiver) < 1) { warning(0, "cimd_submit_smsmessage: ignoring message with 0-length field"); goto okay; /* THIS IS NOT OKAY!!!! XXX */ } tmpbuff = gw_malloc(10 * 1024); tmptext = gw_malloc(10 * 1024); memset(tmpbuff, 0, 10*1024); memset(tmptext, 0, 10*1024); memset(msgtext, 0, sizeof(msgtext)); if (octstr_len(msg->sms.udhdata)) { octstr_get_many_chars(msgtext, msg->sms.udhdata, 0, octstr_len(msg->sms.udhdata)); octstr_get_many_chars(msgtext + octstr_len(msg->sms.udhdata), msg->sms.msgdata, 0, 140 - octstr_len(msg->sms.udhdata)); } else { octstr_get_many_chars(msgtext, msg->sms.msgdata, 0, octstr_len(msg->sms.msgdata)); } /* XXX parse_iso88591_to_cimd should use Octstr * directly, or get a char* and a length, instead of using NUL * terminated strings. */ parse_iso88591_to_cimd(msgtext, tmptext, 10*1024, smsc->alt_charset); /* If messages has UDHs, add the magic number 31 to the right spot */ sprintf(tmpbuff, "%c%s%c%s%c%s%c%s%c%s%c%s%c%s%c%c", 0x02, "03", 0x09, octstr_get_cstr(msg->sms.receiver), 0x09, tmptext, 0x09, "", 0x09, "", 0x09, (octstr_len(msg->sms.udhdata)) ? "31" : "", 0x09, "11", 0x03, 0x0A); ret = write_to_socket(smsc->socket, tmpbuff); if (ret < 0) { debug("bb.sms.cimd", 0, "cimd_submit_smsmessage: socket write error"); goto error; } /* The Nokia SMSC MAY be configured to send delivery information, which we then will HAVE to acknowledge. Naturally the CIMD 1.3 protocol does not include any kind of negotiation mechanism. */ ret = expect_acknowledge(smsc, &cmd, &err); if (ret >= 1) { if (cmd == 4) { send_acknowledge(smsc); goto okay; } else if (cmd == 3) { goto okay; } } else if (ret == 0) { if (cmd == 4) { send_acknowledge(smsc); goto okay; /* FIXME XXX THIS IS BOGUS, FIX SMSGATEWAY.C */ goto error; } else if (cmd == 3) { goto okay; /* FIXME XXX THIS IS BOGUS, FIX SMSGATEWAY.C */ goto error; } else { error(0, "Unexpected behaviour from the CIMD server"); debug("bb.sms.cimd", 0, "cimd_submit_smsmessage: acknowledge was <%i>", ret); debug("bb.sms.cimd", 0, "cimd_submit_smsmessage: buffer==<%s>", smsc->buffer); goto error; } } okay: gw_free(tmpbuff); gw_free(tmptext); return 0; error: debug("bb.sms.cimd", 0, "cimd_submit_smsmessage: returning error"); gw_free(tmpbuff); gw_free(tmptext); return -1; }
/** * Handle a player request for the list of bans* * * @param data the request packet * @param len the length of data * @param cli_addr the address of the sender * @param cli_len the length of cli_addr */ void *c_req_list_bans(char *data, unsigned int len, struct player *pl) { send_acknowledge(pl); /* ACK */ s_resp_bans(pl); return NULL; }