1 /****************************************************************************
2 Copyright (c) 2012, Intel Corporation
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 1. Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
15 3. Neither the name of the Intel Corporation nor the names of its
16 contributors may be used to endorse or promote products derived from
17 this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
31 ******************************************************************************/
33 * MVRP protocol (part of 802.1Q-2011)
46 int mvrp_send_notifications(struct mvrp_attribute *attrib, int notify);
49 unsigned char MVRP_CUSTOMER_BRIDGE_ADDR[] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x21 }; /* 81-00 */
50 unsigned char MVRP_PROVIDER_BRIDGE_ADDR[] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x0D }; /* 88-A8 */
52 extern unsigned char STATION_ADDR[];
54 /* global variables */
56 struct mvrp_database *MVRP_db;
60 struct mvrp_attribute *mvrp_lookup(struct mvrp_attribute *rattrib)
62 struct mvrp_attribute *attrib;
64 attrib = MVRP_db->attrib_list;
65 while (NULL != attrib) {
66 if (attrib->attribute == rattrib->attribute)
68 attrib = attrib->next;
73 int mvrp_add(struct mvrp_attribute *rattrib)
75 struct mvrp_attribute *attrib;
76 struct mvrp_attribute *attrib_tail;
78 /* XXX do a lookup first to guarantee uniqueness? */
80 attrib_tail = attrib = MVRP_db->attrib_list;
82 while (NULL != attrib) {
83 if (attrib->attribute < rattrib->attribute) {
84 /* possible tail insertion ... */
85 if (NULL != attrib->next) {
86 attrib = attrib->next;
89 rattrib->next = attrib->next;
90 rattrib->prev = attrib;
91 attrib->next = rattrib;
95 /* head insertion ... */
96 rattrib->next = attrib;
97 rattrib->prev = attrib->prev;
98 attrib->prev = rattrib;
99 if (NULL != rattrib->prev)
100 rattrib->prev->next = rattrib;
102 MVRP_db->attrib_list = rattrib;
106 attrib_tail = attrib;
107 attrib = attrib->next;
110 /* if we are here we didn't need to stitch in a a sorted entry
111 * so append it onto the tail (if it exists)
114 if (NULL == attrib_tail) {
115 rattrib->next = NULL;
116 rattrib->prev = NULL;
117 MVRP_db->attrib_list = rattrib;
119 rattrib->next = NULL;
120 rattrib->prev = attrib_tail;
121 attrib_tail->next = rattrib;
127 int mvrp_merge(struct mvrp_attribute *rattrib)
129 struct mvrp_attribute *attrib;
131 attrib = mvrp_lookup(rattrib);
134 return -1; /* shouldn't happen */
136 /* primarily we update the last mac address state for diagnostics */
137 memcpy(attrib->registrar.macaddr, rattrib->registrar.macaddr, 6);
141 int mvrp_event(int event, struct mvrp_attribute *rattrib)
143 struct mvrp_attribute *attrib;
147 case MRP_EVENT_LVATIMER:
148 mrp_jointimer_stop(&(MVRP_db->mrp_db));
150 attrib = MVRP_db->attrib_list;
152 while (NULL != attrib) {
153 mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_TXLA);
154 mrp_registrar_fsm(&(attrib->registrar),
155 &(MVRP_db->mrp_db), MRP_EVENT_TXLA);
156 attrib = attrib->next;
159 mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_LVATIMER);
164 mrp_jointimer_stop(&(MVRP_db->mrp_db));
166 attrib = MVRP_db->attrib_list;
168 while (NULL != attrib) {
169 mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_RLA);
170 mrp_registrar_fsm(&(attrib->registrar),
171 &(MVRP_db->mrp_db), MRP_EVENT_RLA);
172 attrib = attrib->next;
175 mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_RLA);
179 mrp_jointimer_stop(&(MVRP_db->mrp_db));
180 attrib = MVRP_db->attrib_list;
182 while (NULL != attrib) {
183 mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_TX);
184 attrib = attrib->next;
187 mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_TX);
191 case MRP_EVENT_LVTIMER:
192 mrp_lvtimer_stop(&(MVRP_db->mrp_db));
193 attrib = MVRP_db->attrib_list;
195 while (NULL != attrib) {
196 mrp_registrar_fsm(&(attrib->registrar),
200 attrib = attrib->next;
203 case MRP_EVENT_PERIODIC:
204 attrib = MVRP_db->attrib_list;
206 while (NULL != attrib) {
207 mrp_applicant_fsm(&(attrib->applicant),
209 attrib = attrib->next;
215 case MRP_EVENT_RJOININ:
216 case MRP_EVENT_RJOINMT:
221 mrp_jointimer_start(&(MVRP_db->mrp_db));
223 return -1; /* XXX internal fault */
226 attrib = mvrp_lookup(rattrib);
228 if (NULL == attrib) {
236 mrp_applicant_fsm(&(attrib->applicant), event);
237 /* remap local requests into registrar events */
240 mrp_registrar_fsm(&(attrib->registrar),
241 &(MVRP_db->mrp_db), MRP_EVENT_RNEW);
244 if (MRP_IN_STATE == attrib->registrar.mrp_state)
245 mrp_registrar_fsm(&(attrib->registrar),
249 mrp_registrar_fsm(&(attrib->registrar),
254 mrp_registrar_fsm(&(attrib->registrar),
255 &(MVRP_db->mrp_db), MRP_EVENT_RLV);
258 rc = mrp_registrar_fsm(&(attrib->registrar),
259 &(MVRP_db->mrp_db), event);
262 ("MVRP registrar error on attrib->attribute = %d\n",
273 * XXX should honor the MVRP_db->mrp_db.registration and
274 * MVRP_db->mrp_db.participant controls
277 /* generate local notifications */
278 attrib = MVRP_db->attrib_list;
280 while (NULL != attrib) {
281 if (MRP_NOTIFY_NONE != attrib->registrar.notify) {
282 mvrp_send_notifications(attrib,
283 attrib->registrar.notify);
284 attrib->registrar.notify = MRP_NOTIFY_NONE;
286 attrib = attrib->next;
292 struct mvrp_attribute *mvrp_alloc()
294 struct mvrp_attribute *attrib;
296 attrib = malloc(sizeof(struct mvrp_attribute));
300 memset(attrib, 0, sizeof(struct mvrp_attribute));
302 attrib->applicant.mrp_state = MRP_VO_STATE;
303 attrib->applicant.tx = 0;
304 attrib->applicant.sndmsg = MRP_SND_NULL;
305 attrib->applicant.encode = MRP_ENCODE_OPTIONAL;
307 attrib->registrar.mrp_state = MRP_MT_STATE;
308 attrib->registrar.notify = MRP_NOTIFY_NONE;
313 int mvrp_recv_msg(void)
319 mrpdu_message_t *mrpdu_msg;
320 unsigned char *mrpdu_msg_ptr;
321 unsigned char *mrpdu_msg_eof;
322 mrpdu_vectorattrib_t *mrpdu_vectorptr;
324 uint16_t numvalues_processed;
330 uint16_t vid_firstval;
331 struct mvrp_attribute *attrib;
334 bytes = mrpd_recvmsgbuf(mvrp_socket, &msgbuf);
338 if ((unsigned int)bytes < (sizeof(eth_hdr_t) + sizeof(mrpdu_t) +
339 sizeof(mrpdu_message_t)))
342 eth = (eth_hdr_t *) msgbuf;
344 /* note that MVRP frames should always arrive untagged (no vlan) */
345 if (MVRP_ETYPE != ntohs(eth->typelen))
348 /* XXX check dest mac address too? */
350 mrpdu = (mrpdu_t *) (msgbuf + sizeof(struct eth_hdr));
353 * ProtocolVersion handling - a receiver must process received frames with a lesser
354 * protocol version consistent with the older protocol processing requirements (e.g. a V2
355 * agent receives a V1 message, the V1 message should be parsed with V1 rules).
357 * However - if an agent receives a NEWER protocol, the agent should still attempt
358 * to parse the frame. If the agent finds an AttributeType not recognized
359 * the agent discards the current message including any associated trailing vectors
360 * up to the end-mark, and resumes with the next message or until the end of the PDU
363 * If a VectorAttribute is found with an unknown Event for the Type, the specific
364 * VectorAttrute is discarded and processing continues with the next VectorAttribute.
367 if (MVRP_PROT_VER != mrpdu->ProtocolVersion) /* XXX should accept ... */
370 mrpdu_msg_ptr = (unsigned char *)MRPD_GET_MRPDU_MESSAGE_LIST(mrpdu);
372 mrpdu_msg_eof = (unsigned char *)mrpdu_msg_ptr;
373 mrpdu_msg_eof += bytes;
374 mrpdu_msg_eof -= sizeof(eth_hdr_t);
375 mrpdu_msg_eof -= MRPD_OFFSETOF_MRPD_GET_MRPDU_MESSAGE_LIST;
378 * MVRP_VID_TYPE FirstValue is the 12 bit (2-byte) VLAN with
379 * corresponding attrib_length=2
381 * MVRP uses ThreePackedEvents for all vector encodings
383 * walk list until we run to the end of the PDU, or encounter a double end-mark
388 while (mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) {
389 mrpdu_msg = (mrpdu_message_t *) mrpdu_msg_ptr;
390 if ((mrpdu_msg->AttributeType == 0) &&
391 (mrpdu_msg->AttributeLength == 0)) {
395 continue; /* end-mark of message-list */
397 break; /* two endmarks - end of message list */
402 switch (mrpdu_msg->AttributeType) {
404 if (mrpdu_msg->AttributeLength != 2) {
405 /* we can seek for an endmark to recover .. but this version
406 * dumps the entire packet as malformed
410 /* AttributeListLength not used for MVRP, hence
411 * Data points to the beginning of the VectorAttributes
414 (mrpdu_vectorattrib_t *) mrpdu_msg->Data;
415 mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
417 while (!((mrpdu_msg_ptr[0] == 0)
418 && (mrpdu_msg_ptr[1] == 0))) {
420 MRPDU_VECT_NUMVALUES(ntohs
425 /* Malformed - cant tell how long the trailing vectors are */
428 if ((mrpdu_vectorptr->FirstValue_VectorEvents +
429 numvalues / 3) >= mrpdu_msg_eof)
430 /* Malformed - runs off the end of the pdu */
433 vid_firstval = (((uint16_t)
435 FirstValue_VectorEvents[0]) <<
438 FirstValue_VectorEvents[1];
440 /* if not an even multiple ... */
441 if (numvalues != ((numvalues / 3) * 3))
442 numvectorbytes = (numvalues / 3) + 1;
444 numvectorbytes = (numvalues / 3);
447 vectidx <= (numvectorbytes + 2);
451 FirstValue_VectorEvents[vectidx];
452 vectevt[0] = vect_3pack / 36;
454 (vect_3pack - vectevt[0] * 36) / 6;
456 vect_3pack - (36 * vectevt[0]) -
459 numvalues_processed =
460 (numvalues > 3 ? 3 : numvalues);
462 for (vectevt_idx = 0;
463 vectevt_idx < numvalues_processed;
466 if (0xFFF < vid_firstval) /*discard junk */
469 attrib = mvrp_alloc();
471 goto out; /* oops - internal error */
476 memcpy(attrib->registrar.
477 macaddr, eth->srcaddr,
480 switch (vectevt[vectevt_idx]) {
516 numvalues -= numvalues_processed;
520 (ntohs(mrpdu_vectorptr->VectorHeader)))
521 mvrp_event(MRP_EVENT_RLA, NULL);
523 /* 1 byte Type, 1 byte Len, 2 byte FirstValue, and (n) vector bytes */
524 mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
525 mrpdu_msg_ptr += 4 + numvectorbytes;
528 (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
532 /* unrecognized attribute type
533 * we can seek for an endmark to recover .. but this version
534 * dumps the entire packet as malformed
549 mvrp_emit_vidvectors(unsigned char *msgbuf, unsigned char *msgbuf_eof,
550 int *bytes_used, int lva)
552 mrpdu_vectorattrib_t *mrpdu_vectorptr;
556 unsigned int vectevt[3];
558 uint16_t vid_firstval;
559 struct mvrp_attribute *attrib, *vattrib;
560 mrpdu_message_t *mrpdu_msg;
562 unsigned char *mrpdu_msg_ptr = msgbuf;
563 unsigned char *mrpdu_msg_eof = msgbuf_eof;
565 /* need at least 6 bytes for a single vector */
566 if (mrpdu_msg_ptr > (mrpdu_msg_eof - 6))
569 mrpdu_msg = (mrpdu_message_t *) mrpdu_msg_ptr;
570 mrpdu_msg->AttributeType = MVRP_VID_TYPE;
571 mrpdu_msg->AttributeLength = 2;
573 attrib = MVRP_db->attrib_list;
575 mrpdu_vectorptr = (mrpdu_vectorattrib_t *) mrpdu_msg->Data;
577 while ((mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) && (NULL != attrib)) {
579 if (0 == attrib->applicant.tx) {
580 attrib = attrib->next;
583 if (MRP_ENCODE_OPTIONAL == attrib->applicant.encode) {
584 attrib->applicant.tx = 0;
585 attrib = attrib->next;
589 /* pointing to at least one attribute which needs to be transmitted */
590 attrib->applicant.tx = 0;
591 vid_firstval = attrib->attribute;
592 mrpdu_vectorptr->FirstValue_VectorEvents[0] =
593 (uint8_t) (attrib->attribute >> 8);
594 mrpdu_vectorptr->FirstValue_VectorEvents[1] =
595 (uint8_t) (attrib->attribute);
597 switch (attrib->applicant.sndmsg) {
600 * If 'In' in indicated by the applicant attribute, the
601 * look at the registrar state to determine whether to
602 * send an In (if registrar is also In) or an Mt if the
603 * registrar is either Mt or Lv.
605 if (MRP_IN_STATE == attrib->registrar.mrp_state)
606 vectevt[0] = MRPDU_IN;
608 vectevt[0] = MRPDU_MT;
611 vectevt[0] = MRPDU_NEW;
614 vectevt[0] = MRPDU_LV;
617 /* IF 'Join' in indicated by the applicant, look at
618 * the corresponding registrar state to determine whether
619 * to send a JoinIn (if the registar state is 'In') or
620 * a JoinMt if the registrar state is MT or LV.
622 if (MRP_IN_STATE == attrib->registrar.mrp_state)
623 vectevt[0] = MRPDU_JOININ;
625 vectevt[0] = MRPDU_JOINMT;
638 /* now attempt to vectorize contiguous other attributes
639 * which also need to be transmitted
643 vattrib = attrib->next;
645 while (NULL != vattrib) {
646 if (0 == vattrib->applicant.tx)
651 if (vattrib->attribute != vid_firstval)
654 vattrib->applicant.tx = 0;
656 switch (vattrib->applicant.sndmsg) {
659 * If 'In' in indicated by the applicant attribute, the
660 * look at the registrar state to determine whether to
661 * send an In (if registrar is also In) or an Mt if the
662 * registrar is either Mt or Lv.
665 vattrib->registrar.mrp_state)
666 vectevt[vectevt_idx] = MRPDU_IN;
668 vectevt[vectevt_idx] = MRPDU_MT;
671 vectevt[vectevt_idx] = MRPDU_NEW;
674 vectevt[vectevt_idx] = MRPDU_LV;
677 /* IF 'Join' in indicated by the applicant, look at
678 * the corresponding registrar state to determine whether
679 * to send a JoinIn (if the registar state is 'In') or
680 * a JoinMt if the registrar state is MT or LV.
682 if (MRP_IN_STATE == attrib->registrar.mrp_state)
683 vectevt[vectevt_idx] = MRPDU_JOININ;
685 vectevt[vectevt_idx] = MRPDU_JOINMT;
696 if (vectevt_idx > 2) {
697 vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
701 mrpdu_vectorptr->FirstValue_VectorEvents
702 [vectidx] = vect_3pack;
710 if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx])
711 > (mrpdu_msg_eof - 2))
714 vattrib = vattrib->next;
717 /* handle any trailers */
718 if (vectevt_idx > 0) {
719 vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
720 vectevt[1], vectevt[2]);
722 mrpdu_vectorptr->FirstValue_VectorEvents[vectidx] =
727 if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]) >
731 mrpdu_vectorptr->VectorHeader = MRPDU_VECT_NUMVALUES(numvalues);
734 mrpdu_vectorptr->VectorHeader |= MRPDU_VECT_LVA(0xFFFF);
736 mrpdu_vectorptr->VectorHeader =
737 htons(mrpdu_vectorptr->VectorHeader);
739 /* 2 byte header, followed by FirstValues/Vectors - remember vectidx starts at 0 */
741 &(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]);
743 attrib = attrib->next;
745 mrpdu_vectorptr = (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
748 if (mrpdu_vectorptr == (mrpdu_vectorattrib_t *) mrpdu_msg->Data) {
759 *bytes_used = (mrpdu_msg_ptr - msgbuf);
762 /* an internal error - caller should assume TXLAF */
769 unsigned char *msgbuf, *msgbuf_wrptr;
774 unsigned char *mrpdu_msg_ptr;
775 unsigned char *mrpdu_msg_eof;
779 msgbuf = (unsigned char *)malloc(MAX_FRAME_SIZE);
784 msgbuf_wrptr = msgbuf;
786 eth = (eth_hdr_t *) msgbuf_wrptr;
788 /* note that MVRP frames should always be untagged (no vlan) */
789 eth->typelen = htons(MVRP_ETYPE);
790 memcpy(eth->destaddr, MVRP_CUSTOMER_BRIDGE_ADDR, sizeof(eth->destaddr));
791 memcpy(eth->srcaddr, STATION_ADDR, sizeof(eth->srcaddr));
793 msgbuf_wrptr += sizeof(eth_hdr_t);
795 mrpdu = (mrpdu_t *) msgbuf_wrptr;
798 * ProtocolVersion handling - a receiver must process received frames with a lesser
799 * protocol version consistent with the older protocol processing requirements (e.g. a V2
800 * agent receives a V1 message, the V1 message should be parsed with V1 rules).
802 * However - if an agent receives a NEWER protocol, the agent should still attempt
803 * to parse the frame. If the agent finds an AttributeType not recognized
804 * the agent discards the current message including any associated trailing vectors
805 * up to the end-mark, and resumes with the next message or until the end of the PDU
808 * If a VectorAttribute is found with an unknown Event for the Type, the specific
809 * VectorAttrute is discarded and processing continues with the next VectorAttribute.
812 mrpdu->ProtocolVersion = MVRP_PROT_VER;
813 mrpdu_msg_ptr = MRPD_GET_MRPDU_MESSAGE_LIST(mrpdu);
814 mrpdu_msg_eof = (unsigned char *)msgbuf + MAX_FRAME_SIZE;
817 * Iterate over all attributes, transmitting those marked
818 * with 'tx', attempting to coalesce multiple contiguous tx attributes
819 * with appropriate vector encodings.
821 * MVRP_VID_TYPE FirstValue is the 2-byte VLAN with
822 * corresponding attrib_length=2
824 * MVRP uses ThreePackedEvents for all vector encodings
826 * the expanded version of the MRPDU looks like
830 * <Variable number of>
831 * LeaveAllEvent | NumberOfValues
832 * <Variable FirstValue>
836 * in effect, each AttributeType present gets its own 'message' with
837 * variable number of vectors. So with MVRP, you will have at most
841 if (MVRP_db->mrp_db.lva.tx) {
843 MVRP_db->mrp_db.lva.tx = 0;
846 rc = mvrp_emit_vidvectors(mrpdu_msg_ptr, mrpdu_msg_eof, &bytes, lva);
850 mrpdu_msg_ptr += bytes;
852 if (mrpdu_msg_ptr == MRPD_GET_MRPDU_MESSAGE_LIST(mrpdu)) {
853 goto out; /* nothing to send */
857 if (mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) {
865 msgbuf_len = mrpdu_msg_ptr - msgbuf;
867 bytes = mrpd_send(mvrp_socket, msgbuf, msgbuf_len, 0);
875 /* caller should assume TXLAF */
879 int mvrp_send_notifications(struct mvrp_attribute *attrib, int notify)
890 msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
894 stage = variant = regsrc = NULL;
896 stage = (char *)malloc(128);
897 variant = (char *)malloc(128);
898 regsrc = (char *)malloc(128);
900 if ((NULL == stage) || (NULL == variant) || (NULL == regsrc))
903 memset(msgbuf, 0, MAX_MRPD_CMDSZ);
905 sprintf(variant, "%04x", attrib->attribute);
907 sprintf(regsrc, "R=%02x%02x%02x%02x%02x%02x",
908 attrib->registrar.macaddr[0],
909 attrib->registrar.macaddr[1],
910 attrib->registrar.macaddr[2],
911 attrib->registrar.macaddr[3],
912 attrib->registrar.macaddr[4], attrib->registrar.macaddr[5]);
913 switch (attrib->registrar.mrp_state) {
915 sprintf(stage, "VIN %s %s\n", variant, regsrc);
918 sprintf(stage, "VLV %s %s\n", variant, regsrc);
921 sprintf(stage, "VMT %s %s\n", variant, regsrc);
929 snprintf(msgbuf, MAX_MRPD_CMDSZ - 1, "VNE %s", stage);
931 case MRP_NOTIFY_JOIN:
932 snprintf(msgbuf, MAX_MRPD_CMDSZ - 1, "VJO %s", stage);
935 snprintf(msgbuf, MAX_MRPD_CMDSZ - 1, "VLE %s", stage);
942 client = MVRP_db->mrp_db.clients;
943 while (NULL != client) {
944 mrpd_send_ctl_msg(&(client->client), msgbuf, MAX_MRPD_CMDSZ);
945 client = client->next;
959 int mvrp_dumptable(struct sockaddr_in *client)
966 struct mvrp_attribute *attrib;
968 msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
972 stage = variant = regsrc = NULL;
974 stage = (char *)malloc(128);
975 variant = (char *)malloc(128);
976 regsrc = (char *)malloc(128);
978 if ((NULL == stage) || (NULL == variant) || (NULL == regsrc))
981 memset(msgbuf, 0, MAX_MRPD_CMDSZ);
983 msgbuf_wrptr = msgbuf;
985 attrib = MVRP_db->attrib_list;
987 while (NULL != attrib) {
988 sprintf(variant, "%04x", attrib->attribute);
989 sprintf(regsrc, "R=%02x%02x%02x%02x%02x%02x",
990 attrib->registrar.macaddr[0],
991 attrib->registrar.macaddr[1],
992 attrib->registrar.macaddr[2],
993 attrib->registrar.macaddr[3],
994 attrib->registrar.macaddr[4],
995 attrib->registrar.macaddr[5]);
996 switch (attrib->registrar.mrp_state) {
998 sprintf(stage, "VIN %s %s\n", variant, regsrc);
1001 sprintf(stage, "VLV %s %s\n", variant, regsrc);
1004 sprintf(stage, "VMT %s %s\n", variant, regsrc);
1009 sprintf(msgbuf_wrptr, "%s", stage);
1010 msgbuf_wrptr += strnlen(stage, 128);
1011 attrib = attrib->next;
1014 mrpd_send_ctl_msg(client, msgbuf, MAX_MRPD_CMDSZ);
1028 /* S-L Withdraw a listener status */
1029 int mvrp_cmd_parse_vid(
1030 char *buf, int buflen,
1031 uint16_t * attribute,
1035 struct parse_param specs[] = {
1036 {"I" PARSE_ASSIGN, parse_u16_04x, attribute},
1042 return parse(buf + 4, buflen - 4, specs, err_index);
1045 int mvrp_cmd_vid(uint16_t attribute, int mrp_event)
1047 struct mvrp_attribute *attrib;
1049 attrib = mvrp_alloc();
1052 attrib->attribute = attribute;
1053 mvrp_event(mrp_event, attrib);
1057 int mvrp_recv_cmd(char *buf, int buflen, struct sockaddr_in *client)
1065 if (NULL == MVRP_db) {
1066 snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
1067 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1071 rc = mrp_client_add(&(MVRP_db->mrp_db.clients), client);
1080 * V?? - query MVRP Registrar VID database
1082 * V++ NEW a VID (XXX: note network disturbance)
1085 if (strncmp(buf, "V??", 3) == 0) {
1086 mvrp_dumptable(client);
1087 } else if (strncmp(buf, "V--", 3)) {
1088 rc = mvrp_cmd_parse_vid(buf, buflen, &vid_param, &err_index);
1091 rc = mvrp_cmd_vid(vid_param, MRP_EVENT_LV);
1094 } else if ((strncmp(buf, "V++", 3) == 0) || (strncmp(buf, "V+?", 3) == 0)){
1095 rc = mvrp_cmd_parse_vid(buf, buflen, &vid_param, &err_index);
1098 if ('?' == buf[2]) {
1099 mrp_event = MRP_EVENT_JOIN;
1101 mrp_event = MRP_EVENT_NEW;
1103 rc = mvrp_cmd_vid(vid_param, mrp_event);
1107 snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
1108 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1114 snprintf(respbuf, sizeof(respbuf) - 1, "ERI %s", buf);
1115 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1119 snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1120 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1127 int mvrp_init(int mvrp_enable)
1131 /* XXX doesn't handle re-start */
1133 mvrp_socket = INVALID_SOCKET;
1136 if (0 == mvrp_enable) {
1140 rc = mrpd_init_protocol_socket(MVRP_ETYPE, &mvrp_socket,
1141 MVRP_CUSTOMER_BRIDGE_ADDR);
1145 MVRP_db = malloc(sizeof(struct mvrp_database));
1147 if (NULL == MVRP_db)
1150 memset(MVRP_db, 0, sizeof(struct mvrp_database));
1152 /* if registration is FIXED or FORBIDDEN
1153 * updates from MRP are discarded, and
1154 * only IN and JOININ messages are sent
1156 MVRP_db->mrp_db.registration = MRP_REGISTRAR_CTL_NORMAL; /* default */
1158 /* if participant role is 'SILENT' (or non-participant)
1159 * applicant doesn't send any messages -
1161 * Note - theoretically configured per-attribute
1163 MVRP_db->mrp_db.participant = MRP_APPLICANT_CTL_NORMAL; /* default */
1165 rc = mrpd_init_timers(&(MVRP_db->mrp_db));
1170 mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_BEGIN);
1174 /* free MVRP_db and related structures */
1178 mrpd_close_socket(mvrp_socket);
1179 mvrp_socket = INVALID_SOCKET;
1184 int mvrp_reclaim(void)
1186 struct mvrp_attribute *vattrib, *free_vattrib;
1187 if (NULL == MVRP_db)
1190 vattrib = MVRP_db->attrib_list;
1191 while (NULL != vattrib) {
1192 if ((vattrib->registrar.mrp_state == MRP_MT_STATE) &&
1193 ((vattrib->applicant.mrp_state == MRP_VO_STATE) ||
1194 (vattrib->applicant.mrp_state == MRP_AO_STATE) ||
1195 (vattrib->applicant.mrp_state == MRP_QO_STATE))) {
1196 if (NULL != vattrib->prev)
1197 vattrib->prev->next = vattrib->next;
1199 MVRP_db->attrib_list = vattrib->next;
1200 if (NULL != vattrib->next)
1201 vattrib->next->prev = vattrib->prev;
1202 free_vattrib = vattrib;
1203 vattrib = vattrib->next;
1204 mvrp_send_notifications(free_vattrib, MRP_NOTIFY_LV);
1207 vattrib = vattrib->next;
1212 void mvrp_bye(struct sockaddr_in *client)
1214 if (NULL != MVRP_db)
1215 mrp_client_delete(&(MVRP_db->mrp_db.clients), client);