4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * CDDL HEADER START
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * The contents of this file are subject to the terms of the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Common Development and Distribution License (the "License").
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * You may not use this file except in compliance with the License.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * or http://www.opensolaris.org/os/licensing.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * See the License for the specific language governing permissions
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * and limitations under the License.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * When distributing Covered Code, include this CDDL HEADER in each
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * If applicable, add the following below this CDDL HEADER, with the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * fields enclosed by brackets "[]" replaced with your own identifying
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * information: Portions Copyright [yyyy] [name of copyright owner]
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * CDDL HEADER END
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Use is subject to license terms.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * bridged - bridging control daemon. This module provides the door-based
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * interface used by user applications to gather bridge status information.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <stdio.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <stdlib.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <unistd.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <fcntl.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/stat.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <sys/types.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <syslog.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <door.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <errno.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <alloca.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <libdlpi.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <libdlbridge.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <stp_in.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include <net/bridge.h>
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include "global.h"
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define DOOR_DIRMODE 0755
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define DOOR_FILEMODE 0444
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int door_fd = -1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic char doorname[MAXPATHLEN];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/*ARGSUSED*/
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibridge_door_server(void *cookie, char *argp, size_t arg_size, door_desc_t *dp,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint_t ndesc)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* LINTED: alignment */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_door_cmd_t *bdc = (bridge_door_cmd_t *)argp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int retv = EINVAL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bridge_door_cfg_t bdcf;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai UID_STP_STATE_T smstate;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai UID_STP_PORT_CFG_T portcfg;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai UID_STP_PORT_STATE_T portstate;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai struct portdata *pdp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int twoints[2];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (arg_size < sizeof (*bdc) || lock_engine() != 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) door_return((char *)&retv, sizeof (retv), NULL, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai switch (bdc->bdc_type) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case bdcBridgeGetConfig:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((retv = STP_IN_stpm_get_cfg(0, &bdcf.bdcf_cfg)) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bdcf.bdcf_prot = protect;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unlock_engine();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) door_return((char *)&bdcf, sizeof (bdcf), NULL, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case bdcBridgeGetState:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((retv = STP_IN_stpm_get_state(0, &smstate)) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unlock_engine();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) door_return((char *)&smstate, sizeof (smstate), NULL, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case bdcBridgeGetPorts: {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai datalink_id_t *dlp;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int *rbuf;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai size_t rlen;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int i, nports;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (nextport == 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai twoints[0] = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rbuf = twoints;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rlen = sizeof (twoints);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rlen = sizeof (int) + nextport * sizeof (datalink_id_t);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rbuf = alloca(rlen);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dlp = (datalink_id_t *)(rbuf + 1);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (i = nports = 0; i < nextport; i++) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (allports[i]->kern_added)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai dlp[nports++] = allports[i]->linkid;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rbuf[0] = nports;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai rlen = sizeof (int) + nports * sizeof (datalink_id_t);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unlock_engine();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) door_return((char *)rbuf, rlen, NULL, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case bdcBridgeGetRefreshCount:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai twoints[0] = refresh_count;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai twoints[1] = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unlock_engine();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) door_return((char *)twoints, sizeof (twoints), NULL, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case bdcPortGetConfig:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((pdp = find_by_linkid(bdc->bdc_linkid)) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai retv = STP_IN_port_get_cfg(0, pdp->port_index, &portcfg);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (retv != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unlock_engine();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) door_return((char *)&portcfg, sizeof (portcfg), NULL, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case bdcPortGetState:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((pdp = find_by_linkid(bdc->bdc_linkid)) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai portstate.port_no = pdp->port_index;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((retv = STP_IN_port_get_state(0, &portstate)) != 0)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (pdp->sdu_failed)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai portstate.state = UID_PORT_BADSDU;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else if (protect != DLADM_BRIDGE_PROT_STP)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai portstate.state = UID_PORT_NON_STP;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else if (pdp->admin_non_stp && pdp->bpdu_protect)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai portstate.state = UID_PORT_DISABLED;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unlock_engine();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) door_return((char *)&portstate, sizeof (portstate),
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai NULL, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case bdcPortGetForwarding:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if ((pdp = find_by_linkid(bdc->bdc_linkid)) == NULL)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai twoints[0] = pdp->admin_status ? 1 : 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai twoints[1] = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unlock_engine();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) door_return((char *)twoints, sizeof (twoints), NULL, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unlock_engine();
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) door_return((char *)&retv, sizeof (retv), NULL, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaicleanup_door(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (door_fd != -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) door_revoke(door_fd);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai door_fd = -1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (doorname[0] != '\0') {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) unlink(doorname);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai doorname[0] = '\0';
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaivoid
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiinit_door(void)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai int fd;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Make sure that the control directory exists */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) mkdir(DOOR_DIRNAME, DOOR_DIRMODE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Each instance gets a separate door. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) snprintf(doorname, sizeof (doorname), "%s/%s", DOOR_DIRNAME,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai instance_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Do a low-overhead "touch" on the file that will be the door node. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai fd = open(doorname,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | O_NONBLOCK,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DOOR_FILEMODE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (fd != -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) close(fd);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai } else if (errno != EEXIST) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "unable to create control door node: %m");
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai exit(EXIT_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) atexit(cleanup_door);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Create the door. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai door_fd = door_create(bridge_door_server, NULL,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai DOOR_REFUSE_DESC | DOOR_NO_CANCEL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (door_fd == -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "unable to create control door: %m");
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai exit(EXIT_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* Attach the door to the file. */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) fdetach(doorname);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (fattach(door_fd, doorname) == -1) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai syslog(LOG_ERR, "unable to attach control door: %m");
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai exit(EXIT_FAILURE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}